The CL0116 Solar Lantern Controller IC

solar_kit_assem

I’ve been playing with these simple Solar lantern controller ICs recently. They’re the chips used in most cheap solar garden lights. Akiba and I have built a couple of products around these chips and have more in the works.

They’re pretty amazing ICs given that they cost almost nothing and contain a complete NiMH charge controller, boost converter, and PWM LED driver.

sch_cl0116The basic circuit from the datasheet is shown to the left, and aside from the IC itself you just need to add a single inductor, NiMH battery, solar cell and of course the LEDs to complete the circuit.

It uses the solar cell both to charge the battery and as a light sensor. When voltage from the solar cell falls below 150mV the IC will switch into illumination mode and start powering the LEDs. Rather than a typical current limiting configuration, the IC slightly overdrives the LEDs but uses a 100KHz pulse-train to drive them which they suggest results in >90% efficiency.

Considering the IC basically costs nothing this is pretty impressive. I have a set of 10 ICs+inductors on my shop if anybody else wants to play with them.

FG-100 Soldering Iron Tip Temperature Sensor

fg100

I picked up this cheap soldering iron temperature sensor. I mostly wanted it to check the heat capacity of the various tips I have. I was disappointed that it came with Hakko branding, the supplier just listed it as an FG100 (which is a Hakko model number) but it’s clearly fake.

It does however work pretty well, and I was able to see clear differences between my T12-D12 (1.2mm) tip and T12-D24 (2.4mm). I’ll be performing further tests to see how well the various tips perform and see if I can more accurately gauge the heat capacity of the tips. I also want to use this to check the calibration of cheap Hakko 936 clones that I’ve been picking up from Shenzhen for running workshops.

bigtip_fg100

T12-D24 Tip

IMG_0660

T12-D12 Tip

It comes with a set of 10 K-type thermocouples, in order to insure good heat transfer the soldering iron tip should be wet with solder when you measure the temperature. This unfortunately means the thermocouple can get mucky pretty quickly which is why it’s a replaceable part.

Obviously I’ve also taken the device apart too. Below you can see a couple of pictures of the PCB. It uses a single sided PCB with a die on PCB blob. I’m guessing this is a generic temperature sensing IC.

 

It’s interesting that the PCB has a soldermask, this seems to be a more recent trend with these ultra-cheap single sided PCBs which are commonly used in toys and other low cost products. If you’d like to buy this, I have it in my shop, with the Hakko branding removed. By purchasing from me you support further hacks. In particular I think it’s likely that you add a calibration pot (VR1 on the silk) and fahrenheit mode for people of this disposition.

pcbpcb2

Fiddling with a cheap 5 port dumb switch to add VLANs/port mirroring

IMG_0640

I’ve been hacking away at this cheap Shenzhen switch. If you’re interested in hacking on it, you can buy the exact model on my shop here. This also helps fund these hacks.

I picked up this switch on eBay. The seller described it as a gigabit switch, however when I opened it up it contained a IP178GH which is a 10/100 switch on a chip. Some googling locates a pretty decent datasheet for this IC (local copy: IP178G_IC).

While it’s only a 10/100 switch the datasheet is pretty interesting and shows it contains a full management interface. While it contains VLAN and other functionality, I was particularly interested in the port mirroring, which comes in handy when debugging network traffic (port mirroring forwards all TX and RX traffic to another port on the switch where you can monitor it with a packet sniffer like wireshark).

The datasheet describes how the management interface can be used. There are 2 modes of operation. One is that configuration can be loaded from SPI flash. The board contains an unpopulated footprint for the SPI flash, and at some point I plan to try this out.

However there’s a second “Serial Management Interface” which allows the switch configuration to be changed on the fly from an external microcontroller. Conveniently the 2 pins required are broken out on the board:

ip178_pcb

It seems they are also 5v tolerant, which means we can just throw an Arduino at them and bit bang an interface. Here’s my rather messy setup:

IMG_0639

The interface is a pretty simple half-duplex serial interface. There’s a timing diagram in the datasheet, though I didn’t see any clear information about clock speed. I used a clock rate of about 1KHz which seemed to work (I honest didn’t read the datasheet in detail, full details might be there somewhere).

ip178gh_timing

It also contains a full description of the register configuration. As I was particularly interesting in the mirroring config, and the example below programs these registers, here it is:

mirroring

With this in hand I was able to program phy 20 registers 3 and 4 to enable port mirroring from port 0 to port 1 and confirm that this worked correctly. The hacky Arduino code I wrote the included below, you should attach the clock to pin 2, data to pin 3 and make sure the ground is correctly connected.

The code is a mess, but it might prove useful if you’re trying to replicate this work.


int clock_pin = 2;
int data_pin  = 3;

int width=100;

void setup() {
  pinMode(clock_pin, OUTPUT); // CLOCK
  pinMode( data_pin, OUTPUT); // DATA
}

int recv_one_bit() {
  //Serial.print("1r");
  int data=0;
  digitalWrite(clock_pin,0);
  delayMicroseconds(width);
  digitalWrite(clock_pin,1);
  delayMicroseconds(width/2);
  data = digitalRead(data_pin);
  delayMicroseconds(width/2);
  digitalWrite(clock_pin,0);
  return data;
}

void send_data_bit(int data) {
  //Serial.print("1s");
  digitalWrite(clock_pin,0);
  delayMicroseconds(width/2);
  digitalWrite(data_pin,data);
  delayMicroseconds(width/2);
  digitalWrite(clock_pin,1);
  delayMicroseconds(width);
  digitalWrite(clock_pin,0);
}

void outhigh() {
  pinMode(data_pin,OUTPUT);
  digitalWrite(data_pin,1);
  digitalWrite(clock_pin,0);
}

void send_data(uint32_t data,int len) {

  for(int32_t n=len-1;n>=0;n--) {
  //for(int32_t n=0;n<len;n) {
    if(data & ((uint32_t)1 << n)) {
      send_data_bit(1);
    } else {
      send_data_bit(0);
    }
  }
}

uint32_t recv_data(int len) {

  //Serial.print("len: ");
  //Serial.println(len,DEC);
  uint32_t datain = 0;
  for(int32_t n=(len-1);n>=0;n--) {
    //Serial.println(n);
    int d = recv_one_bit();
    if(d != 0) {
      datain = datain | (uint32_t)((uint32_t)1 << n);
     // Serial.println("h");
     // Serial.println(((uint32_t)1<<n),HEX);
      //Serial.println(datain,HEX);
    }
  }
  return datain;
}

uint32_t read_op(int phy,int reg) {
  
  pinMode(data_pin,OUTPUT);
  send_data_bit(1);
  
  send_data_bit(0);
  send_data_bit(1);
  send_data_bit(1);
  send_data_bit(0);
  
  //send_data(1,2); // start bits
  //send_data(2,2); // read operation
  send_data(phy,5);
  send_data(reg,5);

  pinMode(data_pin,INPUT);//INPUT_PULLUP
  
  uint32_t in;
  int inA = recv_one_bit(); // turn around
  //int inB = recv_one_bit(); // this should be required as per spec, but a bit gets missed if I use it.
  
  in = recv_data(16);

  Serial.println("ta bits:");
  Serial.println(inA);
  //Serial.println(inB);

  outhigh();
  //send_data_bit(1);
  
  return in;
}


void write_op(int phy,int reg,uint32_t data) {
  
  pinMode(data_pin,OUTPUT);
  send_data_bit(1);

  send_data_bit(0);
  send_data_bit(1);
  send_data_bit(0);
  send_data_bit(1);
        
  send_data(phy,5);
  send_data(reg,5);
  
  send_data_bit(1);
  send_data_bit(0);
//  send_data(2,2); // Turnaround
  
  send_data(data,16);
}


void loop()
{
  Serial.begin(115200);
  
  outhigh();
  delay(1000); // one second
  
  uint32_t data = read_op(20,3);
  Serial.print("Old Read3: ");
  Serial.println(data,HEX);
  
  data = read_op(20,4);
  Serial.print("Old Read4: ");
  Serial.println(data,HEX);
  
  //Port mirroring config sits in phy 20, regs 3 and 4.
  //The bit pattern is shown below. See the datasheet for further details.
  //15.......................0  
  //   enable, mode, res, mirrored port rx
  //3: 1,   11,00000,00000001
  //
  //   monitoring port, res, mirrored port tx
  //4: 001 ,00000,00000001  
  
  uint32_t reg3 = 0xE001;
  uint32_t reg4 = 0x2001;
  
  write_op(20,3,reg3);
  write_op(20,4,reg4);
  delay(1000); // one second

  data = read_op(20,1);
  Serial.print("1Read1: ");
  Serial.println(data,HEX);

  data = read_op(20,2);
  Serial.print("1Read2: ");
  Serial.println(data,HEX);  

  data = read_op(20,3);
  Serial.print("2Read3: ");
  Serial.println(data,HEX);

  data = read_op(20,4);
  Serial.print("2Read4: ");
  Serial.println(data,HEX); 
}

Marking intervals in gnuplot graph (with shading)

data

I needed to mark intervals on a gnuplot line plot different colors. Critically, I didn’t want to have to set the y start and end points (as you would if just drawing a rectangle). Turns out you can do this in gnuplot with a rect object and it’ll figure it out, such that it covers the graph area.

Example code is below (the “data” data file should contain x y datapoints 1 set per line in this example):

set terminal postscript eps color
set output "data.eps"

set xlabel "Time"
set ylabel "Magnitude"

set xrange [0:330]

set style rect fc lt -1 fs solid 0.15 noborder
set obj rect from 240, graph 0 to 270, graph 1 fc rgbcolor "red"
set obj rect from 360, graph 0 to 390, graph 1 fc rgbcolor "red"
set obj rect from 420, graph 0 to 450, graph 1 fc rgbcolor "red"
set obj rect from 540, graph 0 to 570, graph 1 fc rgbcolor "red"
set obj rect from 720, graph 0 to 750, graph 1 fc rgbcolor "red"

set style rect fc rgbcolor "yellow"
set obj rect from 60, graph 0 to 90, graph 1
set obj rect from 120, graph 0 to 150, graph 1
set obj rect from 180, graph 0 to 210, graph 1
set obj rect from 300, graph 0 to 330, graph 1

plot "data" u 1:2 with lines