Hello,
I have the code below for a home security system I've been working on. I have a raspberry pi I'm using as display for this system, and I'm expecting messages with checksum & timestamp in return from raspberry pi to ensure the messages are being received. However time to time, this causes arduino to completely freeze.
I used minicom (serial client) on raspberry pi to replicate the issue and test it. If I type a few random characters like "asdf", most of the time I can get Arduino to crash. I get the following on serial monitor (the lines with pi msg received) when this happens:
If I don't attempt reading serial input, nothing happens. I understand many shun using strings and recommend char arrays for text, but on an Arduino Mega, I would expect it should handle a few characters. I would appreciate any insight anyone may have for the reason of these crashes, and any changes I could try to fix it.
byte alarm_status;
bool serial_comm_error=false;
bool verify_pi=false;
bool incSerialDataChk=false;
char receivedChars[64];
byte reserved_byte=00;
String prev_sensor_numbers="F";
String timestamp="0";
String pi_msg_send="";
unsigned long iteration_time;
unsigned long loop_time;
bool expecting_ack=true;
byte pi_timer=0;
void setup(){
Serial2.begin(9600);
Serial.begin(9600);
for (int i=22; i <= 54; i++){
pinMode(i, INPUT_PULLUP);
pinMode(11,OUTPUT);
}
//Read alarm state from sdcard instead of setting to 0 here
alarm_status=0;
}
void loop(){
if (millis()-iteration_time>=1000){
pi_timer++;
iteration_time=millis();
Serial.println("loop begin");
incSerialDataChk=false;
//Alarm sound
digitalWrite(11,LOW);
//Read Connected Sensors
String sensor_numbers=GetReedSensorData();
sensor_numbers=sensor_numbers+","+GetOtherSensorData();
if (alarm_status!=0){CheckAlarmStatus(sensor_numbers);}
if (prev_sensor_numbers!=sensor_numbers||pi_timer>15){
prev_sensor_numbers=sensor_numbers;
pi_timer=0;
timestamp=String(millis());
pi_msg_send=sensor_numbers+",0"+alarm_status+",0"+reserved_byte;
String checksum=CalcChecksum(pi_msg_send);
pi_msg_send="upd,"+timestamp+","+pi_msg_send+","+checksum;
expecting_ack=true;
}
if (expecting_ack==true){
Serial2.println("^"+pi_msg_send+"$");
Serial.println("^"+pi_msg_send+"$");
} else {
Serial2.println("kpl");
}
String pi_msg_recvd=GetPiOutput();
if (pi_msg_recvd.substring(0,3)=="ack" && pi_msg_recvd.substring(4)==timestamp){
expecting_ack=false;
pi_timer=0;
}
if (pi_msg_recvd.substring(0,3)=="rta" && expecting_ack==false){
//ok to arm
}
//Serial.println("loop end");
}
}
String CalcChecksum(String number_string){
Serial.println(number_string);
uint16_t sum1 = 0;
uint16_t sum2 = 0;
String leading_zero="0";
String chksum="";
char cbuf[3];
for (int i=0;i<=21;i+=3){
String temp_str=number_string.substring(i,i+2);
//Serial.println("substr " + temp_str);
temp_str.toCharArray(cbuf,3);
int data=strtoul(cbuf,NULL,16);
sum1 = sum1+data;
sum2 = sum2+sum1;
}
sum1 = sum1%255;
sum2 = sum2%255;
Serial.println(sum1);
Serial.println(sum2);
if (String(sum1,HEX).length()==1){chksum=chksum+leading_zero;}
chksum=chksum+String(sum1,HEX)+",";
if (String(sum2).length()==1){chksum=chksum+leading_zero;}
chksum=chksum+String(sum2,HEX);
Serial.println(chksum);
return chksum;
}
String GetPiOutput(){
String received_serial="";
if (Serial2.available()){
received_serial=ReadSerialInput();
Serial.println("new pi msg received: " + received_serial);
return received_serial;
}
}
String GetReedSensorData(){
String output="";
byte bytearray[4]={0,0,0,0};
int count=0;
String leading_zero="0";
for (int i=22; i <= 53; i++){
int sensorread = digitalRead(i);
byte biti=(i-22)%8;
if(i>22&&biti==0){count++;}
if (sensorread == HIGH){
Serial.println(String(count)+" " + String(biti));
Serial.println(i);
bitWrite(bytearray[count],7-biti,1);
} else {
bitWrite(bytearray[count],7-biti,0);
}
}
for (int i=0;i<=3;i++){
if (String(bytearray[i],HEX).length()==1){
output+=leading_zero;
}
output+=String(bytearray[i],HEX);
if (i<3){output+=",";}
}
Serial.println(output);
return output;
}
String GetOtherSensorData(){
String output="00,00";
return output;
}
String ReadSerialInput() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '^';
char endMarker = '
;
char rc;
int numChars=64;
//char receivedChars[64];
boolean newData = false;
while (Serial2.available() > 0 && newData == false) {
rc = Serial2.read();
//Check for alphanumeric and punctuation
//if (!(isAlphaNumeric(rc)||isPunct(rc)||isSpace(rc))){return "serial error";}
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
if (newData == true) {
newData == false;
incSerialDataChk=true;
return receivedChars;
}
}