Measuring multiple RPM's, arduino crashes

I've adapted this code: Elimeléc's Arduino Projects: Measure RPMs Arduino to read six hall sensors (http://hamlin.com/product-detail.cfm?productid=78)
Every second, it adds up all the values and converts the total to a range of 1-5.
Depending on the outcome, one of five relays is triggered.

Here's a quick video I made of my test setup: www.youtube.com/watch?v=-P-lzth5u-o

When the sensors aren't triggered, everything runs fine (I've got it sitting on my desk for about half an hour now, without any problems) But when the sensors are triggered, I'm experiencing random crashes (the code will just stop and I need to reset the arduino)

I've already tried uncommenting/removing the serialPrints, but that doesn't make a difference.

Any help would be really apreciated

// Source: http://elimelecsarduinoprojects.blogspot.nl/2013/06/measure-rpms-arduino.html 
// read RPM

volatile int rpmcount1 = 0;//see http://arduino.cc/en/Reference/Volatile
volatile int rpmcount2 = 0;
volatile int rpmcount3 = 0;
volatile int rpmcount4 = 0;
volatile int rpmcount5 = 0;
volatile int rpmcount6 = 0;

int rpm1 = 0;
int rpm2 = 0;
int rpm3 = 0;
int rpm4 = 0;
int rpm5 = 0;
int rpm6 = 0;

unsigned long lastmillis = 0;

int averageRpm;
int stageOld = 1;
int stageNew = 1; 

int relayPin1 = 8;
int relayPin2 = 9;
int relayPin3 = 10;
int relayPin4 = 11;
int relayPin5 = 12;

void setup(){
 Serial.begin(9600); 
 attachInterrupt(0, hallSensor1, FALLING);//interrupt 0 is on pin 2.
 attachInterrupt(1, hallSensor2, FALLING);//interrupt 1 is on pin 3.
 attachInterrupt(2, hallSensor3, FALLING);//interrupt 2 is on pin 18.
 attachInterrupt(3, hallSensor4, FALLING);//interrupt 3 is on pin 19.
 attachInterrupt(4, hallSensor5, FALLING);//interrupt 4 is on pin 20.
 attachInterrupt(5, hallSensor6, FALLING);//interrupt 5 is on pin 21.
 
 pinMode (relayPin1, OUTPUT);
 pinMode (relayPin2, OUTPUT);
 pinMode (relayPin3, OUTPUT);
 pinMode (relayPin4, OUTPUT);
 pinMode (relayPin5, OUTPUT); 
 
 digitalWrite (relayPin1, HIGH);
 digitalWrite (relayPin2, HIGH);
 digitalWrite (relayPin3, HIGH);
 digitalWrite (relayPin4, HIGH);
 digitalWrite (relayPin5, HIGH);
 
 digitalWrite (relayPin1, LOW);
 delay (100);
 digitalWrite (relayPin1, HIGH);
}

void loop(){
 
 if (millis() - lastmillis == 1000){  //Uptade every one second, this will be equal to reading frecuency (Hz).
 
 detachInterrupt(0);    // Disable interrupt when calculating
 detachInterrupt(1);    
 detachInterrupt(2);    
 detachInterrupt(3);    
 detachInterrupt(4);    
 detachInterrupt(5);    
  
 rpm1 = rpmcount1 * 30;  // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.
 rpm2 = rpmcount2 * 30;
 rpm3 = rpmcount3 * 30;
 rpm4 = rpmcount4 * 30;
 rpm5 = rpmcount5 * 30;
 rpm6 = rpmcount6 * 30;
 
 averageRpm =((rpm1 + rpm2 + rpm3 + rpm4 + rpm5 + rpm6) / 6);
 
 if (averageRpm >= 0 && averageRpm < 40)  {
   stageNew = 1;
 }
 else if (averageRpm >= 40 && averageRpm < 80)  {
   stageNew = 2;
 }
 else if (averageRpm >= 80 && averageRpm < 120)  {
   stageNew = 3;
 }
 else if (averageRpm >= 120 && averageRpm < 160)  {
   stageNew = 4;
 }
 else if (averageRpm >= 160)  {
   stageNew = 5;
 }
 
 switch (stageNew)  {
   case 1:
   if (stageOld == 1)  {     
   }   
   else  {
     digitalWrite (relayPin1, LOW);
     delay (100);
     digitalWrite (relayPin1, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 2:
   if (stageOld == 2)  {
   }
   else  {
   digitalWrite (relayPin2, LOW);
   delay (100);
   digitalWrite (relayPin2, HIGH);
   stageOld = stageNew;
   }
   break;
   
   case 3:
   if (stageOld == 3)  {
   }
   else  {
     digitalWrite (relayPin3, LOW);
     delay (100);
     digitalWrite (relayPin3, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 4:
   if (stageOld == 4)  {
   }
   else  {
     digitalWrite (relayPin4, LOW);
     delay (100);
     digitalWrite (relayPin4, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 5:
   if (stageOld == 5)  {
   }
   else  {
     digitalWrite (relayPin5, LOW);
     delay (100);
     digitalWrite (relayPin5, HIGH);
     stageOld = stageNew;
   }
   break;    
 } 
  
 Serial.print("RPM1 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm1); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount1); //print revolutions per second or Hz. And print new line or enter.
 
 Serial.print("RPM2 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm2); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount2); //print revolutions per second or Hz. And print new line or enter.
  
 Serial.print("RPM3 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm3); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount3); //print revolutions per second or Hz. And print new line or enter.
 
 Serial.print("RPM4 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm4); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount4); //print revolutions per second or Hz. And print new line or enter.
 
 Serial.print("RPM5 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm5); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount5); //print revolutions per second or Hz. And print new line or enter.
 
 Serial.print("RPM6 =\t"); //print the word "RPM" and tab.
 Serial.print(rpm6); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount6); //print revolutions per second or Hz. And print new line or enter.
  
 Serial.print("Stage=\t"); //print the word "Stage".
 Serial.println(stageOld); //print stage. And print new line or enter.
 
 rpmcount1 = 0; // Restart the RPM counter
 rpmcount2 = 0;
 rpmcount3 = 0;
 rpmcount4 = 0;
 rpmcount5 = 0;
 rpmcount6 = 0;
 
 lastmillis = millis(); // Uptade lastmillis
 
 attachInterrupt(0, hallSensor1, FALLING); //enable interrupt
 attachInterrupt(1, hallSensor2, FALLING);
 attachInterrupt(2, hallSensor3, FALLING);
 attachInterrupt(3, hallSensor4, FALLING);
 attachInterrupt(4, hallSensor5, FALLING);
 attachInterrupt(5, hallSensor6, FALLING);
 }
}


void hallSensor1(){ //this code will be executed every time the interrupt 0 (pin2) gets low.
  rpmcount1++;
}

void hallSensor2(){ // this code will be executed every time the interrupt 1 (pin3) gets low.
  rpmcount2++;
}

void hallSensor3(){ // this code will be executed every time the interrupt 2 (pin18) gets low.
  rpmcount3++;
}

void hallSensor4(){ // this code will be executed every time the interrupt 3 (pin19) gets low.
  rpmcount4++;
}

void hallSensor5(){ // this code will be executed every time the interrupt 4 (pin20) gets low.
  rpmcount5++;
}

void hallSensor6(){ // this code will be executed every time the interrupt 5 (pin21) gets low.
  rpmcount6++;
}
 if (millis() - lastmillis == 1000){

You should not assume that the difference between then and now will be EXACTLY 1000 seconds. >= is better.

 detachInterrupt(0);    // Disable interrupt when calculating

But NOT by detaching all interrupts. noInterrupts(); then interrupts();.

Interrupts should be off ONLY while you copy the data. You have them off for a long time.

The comments are an insult to our intelligence.

Arrays would result in a lot less code.

Whether these changes will help, or not, remains to be seen.

Hi,
I only see enough wiring for 2 hall sensors, I think..

Have you got 6 different shafts to measure, or are all sensors looking at the same shaft?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom..... :slight_smile:

Hi Tom,

I was testing with two sensors. The other four will be added later.
I'm going to measure six different shafts (or bicycle wheels, actually)

@PaulS;
Thanks for your insights.
I'm sorry about the comments. They were in the original code I used and I left them in. No bad intentions meant.
This is just a rough first setup of the code, I know it can be cleaned up a lot.
It's my first time working with interrupts. I found the noInterrupts(); / interrupts(); commands when I was researching, but wasn't sure how I should use them, that's why I just copied the attachInterrupt(); / detachInterrup(); part.
I've included your suggestions and it seems to be working better already, thanks for the great tips!

// Source: http://elimelecsarduinoprojects.blogspot.nl/2013/06/measure-rpms-arduino.html 
// read RPM

volatile int rpmcount1 = 0;
volatile int rpmcount2 = 0;
volatile int rpmcount3 = 0;
volatile int rpmcount4 = 0;
volatile int rpmcount5 = 0;
volatile int rpmcount6 = 0;

int rpm1 = 0;
int rpm2 = 0;
int rpm3 = 0;
int rpm4 = 0;
int rpm5 = 0;
int rpm6 = 0;

unsigned long lastmillis = 0;

int averageRpm;
int stageOld = 1;
int stageNew = 1; 

int relayPin1 = 8;
int relayPin2 = 9;
int relayPin3 = 10;
int relayPin4 = 11;
int relayPin5 = 12;

void setup(){
 Serial.begin(9600); 
 attachInterrupt(0, hallSensor1, FALLING);//interrupt 0 is on pin 2.
 attachInterrupt(1, hallSensor2, FALLING);//interrupt 1 is on pin 3.
 attachInterrupt(2, hallSensor3, FALLING);//interrupt 2 is on pin 18.
 attachInterrupt(3, hallSensor4, FALLING);//interrupt 3 is on pin 19.
 attachInterrupt(4, hallSensor5, FALLING);//interrupt 4 is on pin 20.
 attachInterrupt(5, hallSensor6, FALLING);//interrupt 5 is on pin 21.
 
 pinMode (relayPin1, OUTPUT);
 pinMode (relayPin2, OUTPUT);
 pinMode (relayPin3, OUTPUT);
 pinMode (relayPin4, OUTPUT);
 pinMode (relayPin5, OUTPUT); 
 
 digitalWrite (relayPin1, HIGH);
 digitalWrite (relayPin2, HIGH);
 digitalWrite (relayPin3, HIGH);
 digitalWrite (relayPin4, HIGH);
 digitalWrite (relayPin5, HIGH);
 
 digitalWrite (relayPin1, LOW);
 delay (100);
 digitalWrite (relayPin1, HIGH);
}

void loop(){
 
 if (millis() - lastmillis >= 1000){ 
 
 noInterrupts();
  
 rpm1 = rpmcount1 * 30;  // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.
 rpm2 = rpmcount2 * 30;
 rpm3 = rpmcount3 * 30;
 rpm4 = rpmcount4 * 30;
 rpm5 = rpmcount5 * 30;
 rpm6 = rpmcount6 * 30;
 
 interrupts();
 
 averageRpm =((rpm1 + rpm2 + rpm3 + rpm4 + rpm5 + rpm6) / 6);
 
 if (averageRpm >= 0 && averageRpm < 40)  {
   stageNew = 1;
 }
 else if (averageRpm >= 40 && averageRpm < 80)  {
   stageNew = 2;
 }
 else if (averageRpm >= 80 && averageRpm < 120)  {
   stageNew = 3;
 }
 else if (averageRpm >= 120 && averageRpm < 160)  {
   stageNew = 4;
 }
 else if (averageRpm >= 160)  {
   stageNew = 5;
 }
 
 switch (stageNew)  {
   case 1:
   if (stageOld == 1)  {     
   }   
   else  {
     digitalWrite (relayPin1, LOW);
     delay (100);
     digitalWrite (relayPin1, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 2:
   if (stageOld == 2)  {
   }
   else  {
   digitalWrite (relayPin2, LOW);
   delay (100);
   digitalWrite (relayPin2, HIGH);
   stageOld = stageNew;
   }
   break;
   
   case 3:
   if (stageOld == 3)  {
   }
   else  {
     digitalWrite (relayPin3, LOW);
     delay (100);
     digitalWrite (relayPin3, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 4:
   if (stageOld == 4)  {
   }
   else  {
     digitalWrite (relayPin4, LOW);
     delay (100);
     digitalWrite (relayPin4, HIGH);
     stageOld = stageNew;
   }
   break;
   
   case 5:
   if (stageOld == 5)  {
   }
   else  {
     digitalWrite (relayPin5, LOW);
     delay (100);
     digitalWrite (relayPin5, HIGH);
     stageOld = stageNew;
   }
   break;    
 } 
  
 Serial.print("RPM1 =\t"); 
 Serial.print(rpm1); 
 Serial.print("\t Hz=\t");
 Serial.println(rpmcount1);
 
 Serial.print("RPM2 =\t");
 Serial.print(rpm2); 
 Serial.print("\t Hz=\t");
 Serial.println(rpmcount2);
 
 Serial.print("RPM3 =\t");
 Serial.print(rpm3);
 Serial.print("\t Hz=\t");
 Serial.println(rpmcount3);
 
 Serial.print("RPM4 =\t");
 Serial.print(rpm4);
 Serial.print("\t Hz=\t"); 
 Serial.println(rpmcount4);
 
 Serial.print("RPM5 =\t");
 Serial.print(rpm5);
 Serial.print("\t Hz=\t"); 
 Serial.println(rpmcount5);
 
 Serial.print("RPM6 =\t");
 Serial.print(rpm6); 
 Serial.print("\t Hz=\t"); 
 Serial.println(rpmcount6);
  
 Serial.print("Stage=\t");
 Serial.println(stageOld); 
 
 rpmcount1 = 0; 
 rpmcount2 = 0;
 rpmcount3 = 0;
 rpmcount4 = 0;
 rpmcount5 = 0;
 rpmcount6 = 0;
 
 lastmillis = millis();
 }
}


void hallSensor1(){
  rpmcount1++;
}

void hallSensor2(){ 
  rpmcount2++;
}

void hallSensor3(){
  rpmcount3++;
}

void hallSensor4(){
  rpmcount4++;
}

void hallSensor5(){
  rpmcount5++;
}

void hallSensor6(){ 
  rpmcount6++;
}
 attachInterrupt(0, hallSensor1, FALLING);//interrupt 0 is on pin 2.
 attachInterrupt(1, hallSensor2, FALLING);//interrupt 1 is on pin 3.
 attachInterrupt(2, hallSensor3, FALLING);//interrupt 2 is on pin 18. NO, its actually on  pin 21
 attachInterrupt(3, hallSensor4, FALLING);//interrupt 3 is on pin 19. NO, its actually on  pin 20
 attachInterrupt(4, hallSensor5, FALLING);//interrupt 4 is on pin 20. NO, its actually on  pin 19
 attachInterrupt(5, hallSensor6, FALLING);//interrupt 5 is on pin 21. NO, its actually on  pin 18

There is confusion over the interrupt numbers on the Mega. The assignment in the Arduino reference https://www.arduino.cc/en/Reference/AttachInterrupt is correct.

There is a difference between the arduino abstractions used in attachInterrupt() and the actual INT0:INT5 of the ATMega chip and the AVR code.