The receive routine

The receive routine is based on two states: either looking for a device or sampling data from a found device.
There is also a timeout in case a sensors is not transmitting.

void read_port(unsigned char item){

  unsigned char p = 0xFF;
  long delay;
  unsigned char a;
  char b=0;
  unsigned char d = 0 ;
  unsigned char search = 0x17;
 
  int e;
 
  int t = 0;
 
  BCSCTL1 |= RSEL3 | RSEL2 | RSEL1 | RSEL0; // increase speed
  P1DIR = 0xF4;                            // Set P1.2 to output direction
  P1OUT = 0xF8;   // set p1.2 low to leave snooze mode set p1.3 high to mark sample point
 
  TACTL = 0x1E4;    // start timer ACLK /8 continuous mode
 
  for( e = 0; e < 5000 ; e++); // wait to awake from snoze
 
  hit = 0;    // reset hit marker

  while(t < 1500 & hit == 0){

    t = TAR;
   
    d = 0;
 
    p = 0x17;
 
    while(p != 0){   // wait for startbit

      p = P1IN;
 
      p &= 0x02;
 
    }

    delay = 15;

    while(delay > 1)  // half bit extra delay at start
      delay--;
    for(a = 8; a > 0 ; a--){
 
      delay = 33;

      while(delay > 1)
        delay--;

      d = d  >> 1;
 
      P1OUT = 0xF8; // set sample pin

      p = P1IN;
              
      p &= 0x02;
 
      p = p << 6;     // LSB first

      d |= p;
     
    } // one byte ready
//send_char(d);
//BCSCTL1 |= RSEL3 | RSEL2 | RSEL1 | RSEL0; // increase speed
        
    if((search == 0x17) & (d == (0x41 + item ))){
     
      search = 0x16;
     
    } 

    else if(search == 0x16){

      buffer[b++] = d;
     
      if( b > size[item])
        hit = 0x17;
               
    } // end of char 
    delay = 15;

    while(delay > 1)  // half bit extra delay at end
      delay--;
         
  }  // end of timeout
  BCSCTL1 = RSEL2 | RSEL1 | RSEL0; // reduce speed 
  P1OUT = 0xF4;  // set P1.2 high to enter snooze mode
 


The love of a box

The choice of the Otterbox is based on a previous one with more more space, too much space the componts where rumbling around in an almost uncontrolled way.
This solution will be very thight, but I have some faith in proceeding the project.

Does it fit?


Making heavy progress

I managed to cut the PCB in a reasonable size without any bloodshed.
Now comes the ethical part if it is ok not to centre the button around the otterbox membrane.

I will probably take the decision myself without going into deep discussion with my girlfriend which at the moment is studying art-history.

uncentred button


PCB version 0.1

The breadboard version is working stable as far as I tested it.
I have not tested the reception from the Xbee module but that part "should" not cause any problems since it was working last year.

I need to get my etching things together and make some kind of fine art-work.
Perhaps I will try to place the components in a way to make the unit float in proper balance.

The box


Chosing colours

The blue bar in the picture is suposed to show water in the tank.
The green bars are a bit to vague in contrast to the background maybe I have to change colour.
But I am happy with the lowest row showing voltage as current, max and min values.

Display output version 0.1


The stack problem

The stack problem got an explanation by some kind answers from the Yahoo forum.
When calling the same subroutine the compiler tries to save time and space by wating
to adjust the stack pointer.

In my case this will probably not be a problem since I need to insert some delay between the calls to the display (I don't take care of the ACK sent from the display).

Problems with the compiler

I needed a routine for sending rectangles to the display. It ended up with six arguments. When I run the debugger the first four are put into registers and the two last are pushed onto the stack.

When I run the debugger the stack is never adjusted after a return ending up in a stack overflow.
I probably missed some settings in the options for the compiler, but temporarely I solved it by
using global variables for the two last arguments (a little dirty perhaps).

Some simpel ways for the sensors transmit routine

All measurements are converted to ascii, it will take twice as long to send it but it is a lot easier to debug.
Each sensor is identified by a capital letter ie. "A" is data from the solar panel "B" is from the generator.

Send routine for the sensors


void send_package(void){ 
 
  int i;
   
  int d; 

  P1DIR |= 0x0C;                            // Set P1.2 & 3 to output direction
 
  P1OUT &= 0x03;                            // set P1.3 low to mark start of no snooze 
 
  for( d = 0; d < 500 ; d++);
 
  P1OUT |= 0x08;                            // set P1.3 high to mark start transmission 
    
   send_char('A');                          // identify the solar panel by an A
   
   make_string(sample_scaled);              // format and send current amps

   for(i = 0x01; i < 3 ; i++)
    send_char(st[i]);
   
   make_string(sample_max);                 // format and send max

   for(i = 0x01; i < 3 ; i++)
    send_char(st[i]);

   make_string(amp_hour);                   // format and send last hours amps

   for(i = 0x0; i < 3 ; i++)
    send_char(st[i]);
         
   make_string(amp_per_day);               // format and send last 24 hours amps
  
   for(i = 0x0; i < 3 ; i++)
     send_char(st[i]);

   P1OUT |= 0x04;                            // set P1.2 high  
    
   seconds = seconds + 1;
          
   if(seconds >=60){
            
     seconds = 0;
            
     minutes++;
            
     if (minutes >= 60){
              
       minutes = 0;              

       hours++;
       
       calculate_amp_hour(); 
     
       if(hours>=24)
         hours = 0;            
    }   
  } 

void send_char(char p_i){

  int p,i,j; 
 
  P1OUT |= 0x02;
 
  BCSCTL1 |= RSEL3 | RSEL2 | RSEL1 | RSEL0; // increase speed
 
  P1DIR |= 0x02;                            // Set P1.1 to output direction

    p = (int) p_i;
 
    p = p << 1;
   
    p |= 0x200;                           // add start and stop bit
 
  for(i = 0; i < 10 ;i++){
  
    for(j = 0; j < SERIAL_DELAY_9600; j++);
   
    if((p & 0x01) != 0)
           
      P1OUT = 0x02;  // set bit high
   
    else
     
      P1OUT = 0x00;   // set bit low
       
    p = p >> 1;   
   
  } 
 
  P1OUT |= 0x02;
    for(j = 0; j < SERIAL_DELAY; j++);

    BCSCTL1 = RSEL2 | RSEL1 | RSEL0; // reduce speed


void calculate_amp_hour(void){
 
int i;
   
    amp_hour = sum / amp_divider;
    sum = 0;
    sample_max = sample_scaled;
 
    for(i = 23 ; i >= 0 ; i--){
   
      amp_history[i] = amp_history[i-1];  // rotate last 23 hours
     
    }    
   
     amp_history[0] = amp_hour;           // insert latest hour
   
    amp_per_day = 0;
   
    for(i = 23 ; i >= 0 ; i--){
   
      amp_per_day += amp_history[i]; 
     
    }     


Making breadboards

I like to try and keep the connections down to a reasonable small amount.
Sometimes I run the breaboards a full season withot making any PCB.

Since the frequencies are quit low it usually runs ok without any large groud plate.

For this design I probably will try to make a PCB to get it to fit better in the box. 


breadboard


Working out the user interface

This is a real nerd version with green bar showing generated energy and red showing consumed energy.
But perhaps I will be happy with the solution allthough most people would not understand imediately.

Green vs Red


Software for the initial measurement

To make things easy the measurements are based on 1 bit equals 100 mA, this is equal to measure 1 mV over the 10 mOhm measurent resistor. The AD converter is run in a one shot mode, this might be improved with a interrupt version which probably will decrease the average current consumption slightly.

After the conversion is finished the result is scaled to acomplish the 1bit/100mA approach. The scaled sample is added to a sum for later calculation of the amp hours, there is also a value saved to show the max current.

void ad_3(void){

  int status = 0;

  int i; CCTL0 = OUT;                                              // TXD Idle as Mark

  TACTL = TASSEL_1 + MC_2;                            // ACLK, Continuous mode 

  BCSCTL2 |= DIVS_3; // SMCLK/8

  SD16CTL = SD16REFON + SD16SSEL_1;   // Use 1.2V ref,

  SMCLK SD16CCTL0 = SD16DF;                     // twos complement

  SD16INCTL0 = SD16INCH_2;                         // SD16 A2+/- pin 6 & 7

  SD16AE = SD16AE4 + SD16AE5;                   // A2+ and A2-

  for(i=0; i<3600; i++);

  SD16CCTL0 |= SD16SNGL;                            // Single conversion

  SD16CCTL0 |= SD16SC;                                 // Start conversion

  while((status & SD16IFG) == 0)
      status = SD16CCTL0;                                  // Wait until ready

  sampleData = SD16MEM0;                             // Read the sample

  if(sampleData < 0)
      sampleData = -sampleData;

  SD16CTL = 0; // set reference off

  SD16AE = 0; // disable inputs

  scale();

  sum_sample();

  if(sample_scaled > sample_max)
        sample_max = sample_scaled;

}
 
void scale(void){

  unsigned int sample;

  sample = sampleData;

  sample = sample * scale_mult;                 // be careful to multiply first not to lose small values

  sample = sample / scale_div;

  sample_scaled = sample;

}

void sum_sample(void){

    sum += sample_scaled;

}

Oled up and running

I was a little worried I was not following the structured way of writing in the C language the way I at least beleive I manage to do some times. The display requires a syncronicing pattern at start and a turn of string in the end not to break. The internal flash of the display can hold some 80 pictures and I have not decided yet how many of them I am going to use.

Some progress


TI tiny emulator

After being used to run code without any real dubbuging support TI USB emulator is a big improvement.You don't have all the possibilies a bound out emulator have but you get pretty much for $30.

Once the code is loaded you can set two hardware breakpoints, stepping throgh code and scrutinizing variables is very easy. Ocassionally you need to reload the drivers, I have not found out why.The interface to the board is called spybiwire and takes up two wires instead of JTAGs normally four or five wires. In that way you can acess all 8 I/O ports while debugging. 

The small emulator


Xbee as a cable replacement

The Zigbee module I use is a $19 Xbee module. It acts as a cable replacement and you really don't need to know anything about the Zigbee stack. I used a development kit to set it to 38400 kBit and use snooze mode which needs 2 mS to wake up.

Zigbee module


Don't use the P1REN register

I think I missed out part of the bug report or doing something totally wrong. I could not get the serial output to the display correct unless I avoided the register used for pullup/pulldown. But I am happy with the result sofar and now I at least think I have the hardware ok for connecting the display. By the way, what you see on the picture is the sequence 0x59, 0x01, 0x00 which turns off the display without crashing the DC/DC converters (but you probably guessed that already).

monday "stimmung" picture


What is the goal for the "thing"

Because of the small size of the display I will probably go for a solution where the output is a graphical wiew of accumulated amphours the last 24 hours. In that way you will get a quick look at if energy from the solar cell and generator match up to the energy consumed by the refrigerator and the heater. There will also a bar showing water left in the tank and probably some max/min measurement of the voltage.

The smell of soldering

Sometimes I miss the smell of soldering. I get to solder a little but not much when connecting the few wires that are used. The CPU is a standard part you get when buing Texas very inexpensive $30 development kit. For the sensors only 6 wires are used vcc,gnd,data in to the Zigbee, a snooze wire and two wires for differential ADC input. The ADC wires are connected to 10 mOhms measuring resistors. The software takes care of both ways of connections to the resistor. For the receiver part I expect to have connections for data and sleep from the Zigbee, a single button input and a wire activating a relay for power to the display.

The CPU part


Software environment


IAR is working ok

As software environment I am using the IAR kickstart. It is for free for code sizes up to 4K which actually is twice the size of my CPU. From the start I did not beleive I would be able to write the code in C because of the limited size. But sofar I have only manage to hit the ceiling a few times.

Tools to make this small project get forward

On a trip to New York I bought one of the first Asus Eee. This is now dedicated to my boat computer project. Normally the PCs I buy get occupied by someone else in the family but this one is only for me. There is a 11 years old Tektronix oscilloscop that so far been enough to debug the system.If things get really funny I also have a 15 years old logic analyzer.

The working environment


RSS 2.0