Argon random reboots

Have adapted sketch from Bee Counter v2 (written for Arduino) for use with Argon. Goal is to count bees entering and leaving the hive, using 24 gates. Have frequent, random reboots. Code is long but will include it.

......................................................................................................................................................................

const int LATCH = A5; 

#include <LiquidCrystal_I2C_Spark.h>
#include <ThingSpeak.h>

LiquidCrystal_I2C *lcd;
TCPClient client;

int timehour=0;
int timeminute=0;

//unsigned long myChannelNumber =
//const char * myWriteAPIKey = 

//Pins  Argon

const byte powerGates1 = D4;
const byte powerGates2 = D5;


const int numberOfGates = 24; // 24 gates, 48 sensors
const int startGate = 0;  //useful for testing
const int endGate = 24;   //useful for testing
const int debeebounce = 30;

const int outputDelay = 20000;  //prints bee counts every 20 seconds
unsigned long lastOutput = 0;
unsigned long currentTime = 0;   // current time defined by milliseconds after program initiated


//boolean 0 or 1 sensor readings, 1 bee is present
boolean inSensorReading[numberOfGates];
boolean outSensorReading[numberOfGates];

boolean lastInSensorReading[numberOfGates];
boolean lastOutSensorReading[numberOfGates];

boolean checkStateIn[numberOfGates];
boolean checkStateOut[numberOfGates];

int inCount[numberOfGates];
int outCount[numberOfGates];
  
unsigned long startInReadingTime[numberOfGates];
unsigned long startOutReadingTime[numberOfGates];

unsigned long inSensorTime[numberOfGates];
unsigned long outSensorTime[numberOfGates];
 
unsigned long lastInFinishedTime[numberOfGates];
unsigned long lastOutFinishedTime[numberOfGates];
  
unsigned long inReadingTimeHigh[numberOfGates];
unsigned long outReadingTimeHigh[numberOfGates];

unsigned long lastInTime[numberOfGates];
unsigned long lastOutTime[numberOfGates];

unsigned long lastInReadingTimeHigh[numberOfGates];
unsigned long lastOutReadingTimeHigh[numberOfGates];

int totalTimeTravelGoingOut[numberOfGates];
int totalTimeTravelGoingIn[numberOfGates];

int firstTestInVariable[numberOfGates];


int firstTestOutVariable[numberOfGates];


int inTotal;
int outTotal;


int n = 0;


unsigned long target_time = 0 ;   // used to help limiting publishing to every 360 min  (0L)
#define PERIOD 60*60*1000        


void setup ()
{
  
  ThingSpeak.begin(client);  
  lcd = new LiquidCrystal_I2C(0x27, 16, 4);
  lcd->init();
  lcd->backlight();
  
  
      lcd->setCursor(0,0);
      lcd->print("Begin switch test.");
  
   SPI.begin();            //  Assumes LATCH = A5
  SPI.beginTransaction(SPISettings(3*MHZ, MSBFIRST, SPI_MODE2));
  
  
  pinMode (LATCH, OUTPUT);
  digitalWrite (LATCH, HIGH);

  pinMode (powerGates1, OUTPUT);
  digitalWrite(powerGates1, LOW);
  pinMode (powerGates2, OUTPUT);
  digitalWrite(powerGates2, LOW);
  
}  // end of setup

byte switchBank1;
byte oldSwitchBank1; 
byte switchBank2;
byte oldSwitchBank2; 
byte switchBank3;
byte oldSwitchBank3; 
byte switchBank4;
byte oldSwitchBank4; 
byte switchBank5;
byte oldSwitchBank5; 
byte switchBank6;
byte oldSwitchBank6; 
byte switchBank7;
byte oldSwitchBank7; 
byte switchBank8;
byte oldSwitchBank8; 

void loop ()
{
  currentTime = millis();  
  
  
  digitalWrite(powerGates1, HIGH);
  digitalWrite(powerGates2, HIGH);
  delayMicroseconds(75); //first 24 gates only need 15us while gates closer to the end need ~40us-75us
  
  digitalWrite (LATCH, LOW);    // pulse the parallel load latch
  delayMicroseconds(3);
  digitalWrite (LATCH, HIGH);

  delayMicroseconds(3);
  
  digitalWrite(powerGates1, LOW);
  digitalWrite(powerGates2, LOW);

  //Reading 24 bits at 1Mhz should take about 24 microseconds,
  //reading 24 bits at 3Mhz should take about 8us
  //reading 48 bits at 3Mhz should take abotu 16us
  switchBank1 = SPI.transfer (0); //8
  switchBank2 = SPI.transfer (0); //16
  switchBank3 = SPI.transfer (0); //24
  switchBank4 = SPI.transfer (0); //32
  switchBank5 = SPI.transfer (0); //40
  switchBank6 = SPI.transfer (0); //48  
 
  
  
  if(switchBank1 != oldSwitchBank1 || switchBank2 != oldSwitchBank2 || switchBank3 != oldSwitchBank3 || switchBank4 != oldSwitchBank4 || switchBank5 != oldSwitchBank5 || switchBank6 != oldSwitchBank6)
  {
    //convert bytes to gate values
    int gate = 0;
    for(int i = 0; i < 8; i++)
    {
      if((switchBank1 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank1 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;       
      gate++;  
    }
    for(int i = 0; i < 8; i++)
    {
      if((switchBank2 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank2 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;      
      gate++;  
    }
    for(int i = 0; i < 8; i++)
    {
      if((switchBank3 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank3 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;       
      gate++;  
    }
    for(int i = 0; i < 8; i++)
    {
      if((switchBank4 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank4 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;       
      gate++;  
    }
    for(int i = 0; i < 8; i++)
    {
      if((switchBank5 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank5 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;       
      gate++;  
    }
    for(int i = 0; i < 8; i++)
    {
      if((switchBank6 >> i) & 1)
          outSensorReading[gate] = HIGH;
      else outSensorReading[gate] = LOW;
      i++;
      if((switchBank6 >> i) & 1)
          inSensorReading[gate] = HIGH;
      else inSensorReading[gate] = LOW;      
      gate++;  
    }  
    oldSwitchBank1 = switchBank1;
    oldSwitchBank2 = switchBank2;
    oldSwitchBank3 = switchBank3;
    oldSwitchBank4 = switchBank4;
    oldSwitchBank5 = switchBank5;
    oldSwitchBank6 = switchBank6;
  }
  
  for (int i = startGate; i < endGate; i++) 
  //for (int i = 8; i < 12; i++)
  { 
    if(inSensorReading[i] != lastInSensorReading[i])  //change of state on IN sensor
    { 
      checkStateIn[i] = 0;
      lastInSensorReading[i] = inSensorReading[i];
      inSensorTime[i] = currentTime;
      
    } 
    if(outSensorReading[i] != lastOutSensorReading[i])  //change of state on OUT sensor
    { 
      checkStateOut[i] = 0;
      lastOutSensorReading[i] = outSensorReading[i];
      outSensorTime[i] = currentTime;
     
    }       
    if(currentTime - inSensorTime[i] > debeebounce && checkStateIn[i] == 0)  //debounce IN sensor
    {
      checkStateIn[i] = 1; //passed debounce         
      
      if(inSensorReading[i] == HIGH) //a bee just entered the sensor
      {
        startInReadingTime[i] = currentTime;

      }
      if(inSensorReading[i] == LOW)  //a bee just exits the sensor; that is, it was HIGH, now it is LOW (empty)
      {  
        lastInFinishedTime[i] = currentTime;            
        inReadingTimeHigh[i] = currentTime - startInReadingTime[i]; //this variable is how long the bee was present for
        

        if(outReadingTimeHigh[i] < 650 && inReadingTimeHigh[i] < 650){ //should be less than 650ms
          if(currentTime - lastOutFinishedTime[i] < 200){ //the sensors are pretty cose together so the time it takes to trigger on and then the other should be small.. ~200ms
            inTotal++;
            
          }
        }
      }           
    }
    if(currentTime - outSensorTime[i] > debeebounce && checkStateOut[i] == 0)  //debounce OUT sensor
    {
      checkStateOut[i] = 1; //passed debounce         
     
      if(outSensorReading[i] == HIGH) //a bee just entered the sensor
      {
        startOutReadingTime[i] = currentTime;
    
      }
      if(outSensorReading[i] == LOW)  //a bee just exits the sensor; that is, it was HIGH, now it is LOW (empty)
      {  
        lastOutFinishedTime[i] = currentTime;            
        outReadingTimeHigh[i] = currentTime - startOutReadingTime[i]; //this variable is how long the bee was present for
    
        if(outReadingTimeHigh[i] < 600 && inReadingTimeHigh[i] < 600){ //should be less than 600ms
          if(currentTime - lastInFinishedTime[i] < 200){ //the sensors are pretty cose together so this time should be small
            outTotal++;
            
          }
        }
      }          
    }        
  }    

  delay (15);   // debounce

  if (currentTime - lastOutput > outputDelay) 
    {
    
    sendData(); 
    lastOutput = currentTime; 
    inTotal = 0;
    outTotal = 0; 
  }
}
      

void sendData() {
    
    lcd->setCursor(0,0);
      lcd->print("Bee Transit Data  "); 
 lcd->setCursor(0,3);
 lcd->print("T, ");
  lcd->print(outTotal);
  lcd->print(", ");
  lcd->print(inTotal);
  
   ThingSpeak.setField(1,outTotal);  
  
     ThingSpeak.setField(2,inTotal);  
       
       //   Write the fields that you've set all at once.
//	ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
    //	delay(16000);
  
}

For one your code would greatly benefit from using structs and arrays rather than numbered variable names.
But the highest potential for failure I’d locate in your use of gate++ without a guard against incrementing past the end of your arrays.
By the end of your 6 for() loops I’d assume gate to stand at 48 (6*8) but your arrays are only 24 elements long.
Additionally with startGate = 0 and endGate = 24 you are also overshooting by one element. The last index in a xxx[24] array is 23 not 24.

BTW, this

can be simplified to

   outSensorReading[gate] = (switchBank1 >> i) & 1;

To add to what @ScruffR said, your use of SPI.beginTransaction() in setup() with no apparent enabling of a Chip Select for the SPI device and no SPI.endTransaction()` is very confusing. You might want to review how to an SPI device and fix your code accordingly.

1 Like

Yes, I can see the need for better system of arrays rather than the variable names. Roger also on the caution regarding array ends. Appreciate the help with simplification—perhaps elegance?

Reviewed also SPI devices, will make changes.