Project freezes after several hours

( I am reposting here, seems more appropriate than the end of the thread it was on )

I have a project that sends 19 numbers from a wireless remote control ( working fine ) to a decoder/display unit via VirtualWire.

Sometimes it just freezes, there is no data coming out of the micro ( using Shiftout ) but the signal from the RF receiver is fine.

Tonight all the displays decided to blank, when I sent an update from the remote again it worked fine, but last night it just froze with numbers displayed. When I switched the power on and off it worked again.

Can anyone see in my code why it should hang up?

It reads the switch data, compares the PIN numbers ( a security address ) then I sort out the displays that need leading zero blanking, plus I check to see if switches 7 and 8 are set to 0, ( which is how I put the displays into standby ) and then it shiftsout to the 19 shift registers.

I put the flushing bit in when I had the previous problem, I dont think it can do any harm ?

There is a shift register clear pin on the TPIC display chips, but I am not using that ( or the notG pin for blanking ) due to pcb layout simplicity. heres the code:-

//  19 digit receiver
// tile order set by old pcb layout of plugs  HGDABCEFSRQPONMLKJI link across gap data inout
// try flushing SR before sending new lot to get rid of intermittent wrong displays

#include <VirtualWire.h>
#define latchPin 19  // rck
#define clockPin 18  // sck
#define dataPin 16   // ser in
int Rxpin;
int PIN;
int tile [19];

int SW0Pin = 3;               // bits to read in unique address - LSB
int SW1Pin = 4;               // bits to read in unique address
int SW2Pin = 5;               // bits to read in unique address
int SW3Pin = 6;               // bits to read in unique address - MSB
int address = 0;            // bits put together afteer reading switches
int add0;
int add1;
int add2;
int add3;

const byte digitTable [10] = { 
  B01111110, B00110000, B01101101, B01111001, B00110011,      // orig without text switching
  B01011011, B01011111, B01110000, B01111111, B01111011};

const byte blank = B00000000;

void setup()

  pinMode(SW0Pin, INPUT); // LSB of remote Address
  digitalWrite(SW0Pin, HIGH);
  byte add0 = 0; // read the value of SW0
  pinMode(SW1Pin, INPUT); // LSB+1
  digitalWrite(SW1Pin, HIGH);
  byte add1= 0;
  pinMode(SW2Pin, INPUT);  // LSB+2
  digitalWrite(SW2Pin, HIGH);
  byte add2 = 0;
  pinMode(SW3Pin, INPUT);  // MSB of address
  digitalWrite(SW3Pin, HIGH);
  byte add3 = 0;

  add3 = !digitalRead(SW3Pin); 
  add3 = add3 << 3;
  add2 = !digitalRead(SW2Pin);
  add2 = add2 << 2;
  add1 = !digitalRead(SW1Pin);
  add1 = add1 << 1;
  add0 = !digitalRead(SW0Pin);
  address = address|add3;
  address = address|add2;
  address = address|add1;
  address = address|add0;

  Rxpin = address;
  Serial.println("Rx PIN is: ");
  Serial.println(Rxpin, BIN);
  Serial.begin(9600);	// Debugging only

  pinMode ( latchPin, OUTPUT);
  pinMode ( clockPin, OUTPUT);
  pinMode ( dataPin, OUTPUT);

  vw_set_rx_pin(9);        // set Rx
  vw_setup(2400);	 // Bits per sec

void loop () 

  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  delay (20);
  if (vw_get_message(buf, &buflen)) // Non-blocking
    Serial.println("Got: ");  // Show on PC for debugging

    //            CHECK IF PIN NUMBERS MATCH

    PIN = buf[0];   // read Tx PIN number from buffer 0
    if ( PIN == Rxpin ) {   //  everything below only runs if PINs match 

      Serial.println(" PINs match ") ; 
      for ( int t =1 ;t<=19;t++ ) { 
        tile [t] = buf [t];
          show ();
    } // end of if PINs match
  }//  end of if message received 
}  //  end of loop

void show ()

{   //   display numbers generated depending on leading zero blanking requirements of each group of displays
  int dnumber = digitTable [ tile [3] ];  // single digit , no LZblanking
  int gnumber = (tile [2]) ? digitTable [ tile [2]] : 0; // leading zero blanking

  int  hnumber = digitTable [tile [1]];
  int enumber = (tile [7]) ? digitTable [ tile [7]] : 0; // leading zero blanking

  int  fnumber = digitTable [tile [8]];
  int rnumber = (tile [10]) ? digitTable [ tile [10]] : 0; // leading zero blanking

  int  snumber = digitTable [tile [9]];

  int anumber = (  tile [4]) ? digitTable [ tile [4] ] : 0;
  int bnumber = ( tile [4]|| tile [5]) ? digitTable [ tile [5]] : 0; // leading zero blanking
  int  cnumber = digitTable [tile [6]];

  int onumber = (  tile [13]) ? digitTable [ tile [13] ] : 0;
  int pnumber = ( tile [13]|| tile [12]) ? digitTable [ tile [12]] : 0; // leading zero blanking
  int  qnumber = digitTable [tile [11]];


  int lnumber = (  tile [16]) ? digitTable [ tile [16] ] : 0;
  int mnumber = ( tile [16]|| tile [15]) ? digitTable [ tile [15]] : 0; // leading zero blanking
  int  nnumber = digitTable [tile [14]];


  int inumber = (  tile [19]) ? digitTable [ tile [19] ] : 0;
  int jnumber = ( tile [19]|| tile [18]) ? digitTable [ tile [18]] : 0; // leading zero blanking
  int  knumber = digitTable [tile [17]];


if ( tile [7] || tile [8] ) {     // if switches 7 and 8  set to 00 blanks all displays
    digitalWrite(latchPin, LOW); 
   for ( int k=0; k<=20; k++ ){                            // flush out shift register
    shiftOut(dataPin, clockPin, LSBFIRST, blank); 
    delay (20);

    shiftOut(dataPin, clockPin, LSBFIRST, hnumber);  
   // delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, gnumber);
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, dnumber); 
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, anumber);
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, bnumber);   
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, cnumber);
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, enumber); 
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, fnumber); 
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, snumber);  
   // delay (5); 
    shiftOut(dataPin, clockPin, LSBFIRST, rnumber);
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, qnumber); 
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, pnumber);
   // delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, onumber);  
    //delay (5); 
    shiftOut(dataPin, clockPin, LSBFIRST, nnumber);
    //delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, mnumber); 
   // delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, lnumber);
   // delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, knumber); 
   // delay (5);  
    shiftOut(dataPin, clockPin, LSBFIRST, jnumber);
   // delay (5);
    shiftOut(dataPin, clockPin, LSBFIRST, inumber); 
    delay (5);

    digitalWrite(latchPin, HIGH); 
  else {

    digitalWrite(latchPin, LOW);      // blanking all displays
   for ( int k=0; k<=20; k++ ){
    shiftOut(dataPin, clockPin, LSBFIRST, blank); 
  digitalWrite(latchPin, HIGH); 
}  // end of showT function
      for ( int t =1 ;t<=19;t++ ) { 
        tile [t] = buf [t];
          show ();

I can’t say this piece is responsible for the problems but it is wrong. tile only has 19 elements and is zero based but you’re trying to store into element 19 which is one off the end and will probably be stored in SW0Pin.

Thanks sixeyes,

Modified post - I see I had declared the array int tile [19];

Come to think of it I don’t need the “tile” anyway, I can just use the buf [number] anyway.

I was getting confused with another project I have that has an interrupt when a new message comes in, but this one will keep the buffered data until the next loop anyway.

I put for ( int t =1 ;t<=19;t++ ) starting at 1 as I have already read buf[0] for the PIN number, but it wouldn’t have matter if I included it and just ignored it further.

I have only got 3 of the outputs going to LED displays for testing, including number19 which displays OK.

( the real displays are 1000km away on a cricket scoreboard I am upgrading to micro, which I hoped would be reliable :0 )

Using the buf didn’t work, but what I did see was that I had the “show” function inside the loop for copying the buffer data to the tile data

for ( int t =1 ;t<=19;t++ ) { 
        tile [t] = buf [t];
          show ();

How on earth did that manage to work? it would have been running the show function 19 times before all the values were read ?

I have moved the show() to after the for loop, and declared tile as [20], and it seems to be working, but sometimes it worked fine for most of the day… here’s hoping.

To help prevent the error you just had in C it’s better to write you loops using less than rather than less than or equal. That way the loop upper limit indicates the size of the array that needs to be declared.

for ( int t =1 ;t<20;t++ )

instead of

for ( int t =1 ;t<=19;t++ )

Thanks sixeyes ,

That makes sense, and thanks for the tip. Its been running fine for the last 3 hours or so :roll_eyes:

Don't forget that the initial value for the index should be 0, not 1, since it is also used as an array index.

Of course, you might need to change the routine that uses the data in the array, if that routine also indexes from 1.


do you mean this part?

    for ( int t =1 ;t<=19;t++ ) { 
        tile [t] = buf [t];

my newbie plan was to copy the data from buffers 1-19 into the tile array, buffer 0 I had already used to check my pin numbers, but I could change this to

 for ( int t =0 ;t<=19;t++ ) { 
        tile [t] = buf [t];

and just ignore tile 0 if it makes the code better…

after about 6 hours it froze again, when I touched around the chip ( probably the reset pin ) it started again.

I replaced the chip this morning with a new one.

Now I am desperate !

I have a 16Mhz xtal with 22pf caps to ground, a well decoupled 5 volt supply, and a 47k from reset to Vcc with a 100nF to ground.

Should I do anything with the unused inputs? like set them as inputs with pull-ups?

"set them as inputs with pull-ups"

Yes, otherwise they float. Not sure if this has anything to do with hanging tho. Try a smaller reset pullup up also. Arduino designs have 10K from what I've seen.

Thanks Bob, I will try that with tying the inputs, I am even going to change the xtal - I am that desperate :astonished:

I guess I tend to try and make the reset come up much later than needed as a throwback to my cmos days, my first Arduino projects had a 100k and 100nF, but I will try a 10 k and 100nF, CxR = 1 mS which is actually quite a long time at 16 Mhz clocking.

There's nothing in my code you can see that might be filling memory of buffers or whatever is there?

If I could trust the RSSI signal from the receiver, I was contemplating putting it into sleep mode between commands to see if that would solve it ( this scoreboard is for cricket, I don't know if you have ever seen the sport, its as slow as ice hockey is fast , a score update could be 10 minutes or half an hour if they went for tea ! )

I am running this at rather a long range ( 200m ? )for the wireless link to give a reliable signal strength reading though.

I will try the input setting first..

"There's nothing in my code you can see that might be filling memory of buffers or whatever is there? " I don't know John, the code looks pretty straightforward to me, but I'm really more of a hardware guy.

OK I will start by tying the free inputs high, change the xtal, solder everything around the chip again, and keep my fingers crossed ;)

but I will try a 10 k and 100nF,

Is that on the reset line? The data sheet shows no capacitor at all. I always go with the data sheet.

Whoops, I assumed it was a normal power on reset type pin, with a delay to keep it low until Vcc was up and the chip running.

Trying to drag myself into the 21st century.

If it just needs to be tied high, why the resistor at all?

OK , thats if you are pulling it down externally afterthought

OK I have removed the capacitor, set all the unused inputs to pullups and it still freezes after several hours.

if I hook the receivers data to an arduino board as well, that board doesn't hang, i.e. the data is OK from the rf module.

But I could perhaps get the arduino one to print buflen every time it sees a message ( presumably anything with the right datarate? )

I wonder if this has something to do with it, I don't use multiplexing for my displays, all the LED segments are latched by the TPIC shift regs.

So once the data is displayed, the loop is only checking for a correct length message coming in :-


void loop () {


delay (20); if (vw_get_message(buf, &buflen)) // Non-blocking {

that's the loop, I don't now why the delay is in there, I think that was part of the code I copied.

Greg who has a similar problem doesn't have the delay...

I have several units in the field with this same front end ( up until the "got " message, that are running fine without hanging up )

It was hung up again this morning , so I guess I will try putting a switch on the RF modules supply, and just power it up when I want to test it.

Except then there would be no constant white noise coming into the chip, which might confuse it,,,,,,,

Or perhaps I could disconnect the antenna, and wrap the receiver in foil ( test it with the remote to make sure nothing is getting through ) and just fold the foil open to test it every few hours..

Now the plot thickens ! I had left it frozen, and without my rebooting it the displays have changed ( I have only three 7seg displays hooked up for testing ) one is blank, and one has random segments on ( not a number ). The lookup table has only valid patterns on.

And when I sent an update from the remote, it worked and displayed the right numbers again....

Driving me nuts !

Sounds like it's time for a bunch more debugging prints. In particular' I'd be interested to have one in an else on the if(vw_get_message.... Documentation says that it'll return a message whether the CRC is correct or not. Might give some insight into your theory about other folks using that frequency. Also, I doubt that it's relevant, but you have some Serial.print activity in setup before Serial.begin.

Thanks I will have a look at that serial print.

I cant add serial prints for debugging as it only hangs up with the chip plugged into the equipment, if I hook up an arduino board to the same Rx output, it doesnt latch !

Meanwhile I have added vw_wait_rx()

which makes it wait for an input (blocking )

I only need the loop to do anything after getting a message ( my displays are latched, not multiplexed )

It takes many hours to test it though ! I ill change that serial thing in setup anywaay.

I think it must have been a noisy power supply !

Its been working 20 hours OK now since I changed the PSU (and made the loop wait for a new message wit the blocking VirtualWire wait instruction.)

Thanks for the forums help