SoftwareSerial resets arduino pro mini

Hi Guys,
I’m working on a project which involves a zigbee and ir leds

i have a zigbee hooked up to my arduino pro mini over softwareserial (4,5)

Problem : first time when i send 7 bytes over zigbee the everything works fine but second time when i send the 7 bytes i get acknowledgement that it received 7 bytes but the data it read is empty. third time no response after 4 or 5 try the pro mini resets. I tried changing pins to 10,11 but still the same problem.
i want the program to work every time i send the 7 bytes.

Thanks in advance for the help :slight_smile:

#include <IRremote.h>
#include <SoftwareSerial.h>
int gma=0;
#define DID_H 0x54
#define DID_L 0xF1
int px = 0;
int khz = 38; // 38kHz carrier frequency for the NEC protocol
unsigned int onoff[] = {8700,4400,550,1600,550,1600,550,550,500,550,500,550,500,550,500,550,500,1650,500,550,550,1600,550,1600,550,550,500,550,500,550,500,550,500,550,500,550,500,550,500,1650,550,500,550,500,500,550,550,500,550,500,500,550,550,1600,550,550,500,550,500,550,500,1600,550,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500}; //AnalysIR Batch Export (IRremote) - RAW
unsigned int up[] = {8750,4350,600,1550,550,1650,500,550,500,550,500,550,500,550,500,550,500,1650,550,500,550,1600,550,1650,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,1650,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,550,500,500,550,550,500,550,500,550,500,550,500,550,500,500,550,550,500,550,500,550,500,550};
  

SoftwareSerial zb(4,5);
IRsend irsend;


void setup() {
  zb.begin(38400);
  delay(5000);
  zb.print("AT+SETPANID 3301");
   for(int l=0;l<=100;l++)
  {
    zb.read();
    delay(10);
  }
}

void loop() {

  zb.listen();
  if(zb.available()==7)
  {
    if(gma==1)
    {
      zb.print("READ OK");
    }
    byte inc[7];
    bool xmp = false;
    for(int i=0;i<=7;i++)
    {
      inc[i] = zb.read();
    }
    zb.write(inc,sizeof(inc));
    byte crc=0x00;
    
    for(int i=0;i<=5;i++)
    {
       crc = crc ^ inc[i];
    }
    if(crc == inc[6])
    {
      xmp = true;
    }
    else
    {
      xmp = false;
    }

   
    if((inc[0]==0xAF)&&(inc[1]==0x1F)&&(xmp==true))
    {
      if((inc[2]==DID_H)&&(inc[3]==DID_L))
      {
        if(inc[4]==0x11)
        {
          
          execute(inc[5]);
        }
      }
      
    }
    
  }

}

void execute(byte cmd)
{
  if(cmd == 0x11)
  {
    irsend.sendRaw(onoff, sizeof(onoff) / sizeof(onoff[0]), khz);
    ACK();
    
  }
  else if(cmd == 0x16)
  {
    irsend.sendRaw(up, sizeof(up) / sizeof(up[0]), khz);
    ACK();
  }
  else
  {
    NAK();
  }
  gma = 1;
  readh();
  
}

void ACK()
{
  byte ack[6];
  ack[0] = 0xAF;
  ack[1] = 0x1F;
  ack[2] = DID_H;
  ack[3] = DID_L;
  ack[4] = 0x22;
  ack[5] = 0xAA;
  byte crc = 0x00;
  for(int i=0;i<=5;i++)
  {
    crc ^= ack[i];
  }
  ack[6] = crc;
  zb.write(ack,sizeof(ack));
}

void NAK()
{
  byte ack[6];
  ack[0] = 0xAF;
  ack[1] = 0x1F;
  ack[2] = DID_H;
  ack[3] = DID_L;
  ack[4] = 0x22;
  ack[5] = 0xFF;
  byte crc = 0x00;
  for(int i=0;i<=5;i++)
  {
    crc ^= ack[i];
  }
  ack[6] = crc;
  zb.write(ack,sizeof(ack));
}

void getdata()
{
 while(zb.available()>0)
 {
  zb.write(zb.read());
 }
}

void readh()
{
   for(int l=0;l<=50;l++)
  {
    zb.read();
    //delay(2);
  }
}

Images from Original Post so we don’t have to download them. See this Image Guide

c7b30b872ae8497512ea83890d7b36f1b78db054.jpg

76042b375bfe04fe190eb974a4f548ea99604d23.jpg

8d5878b03d05b0e34646566a604f2c231e0b76dc.jpg

…R

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. Notice how they don't rely on delay().

It would be a big help if you could describe how your program is supposed to work - i.e. a walk-through of the code.

The data you send in ACK and NAK looks like it could be figured out while you are writing the program and included as a pre-defined byte array

...R

You are overwriting the array here:

    byte inc[7];
    bool xmp = false;
    for(int i=0;i<=7;i++)
    {
      inc[i] = zb.read();
    }

I think you want:

    byte inc[7];
    bool xmp = false;
    for(int i=0;i<7;i++)
    {
      inc[i] = zb.read();
    }

In my opinion you should use a "bloking" condition before every read()

Example: While serial.available()==0{}

It would block your code until there are data coming from your serial device I also suggest to add a timeout, if you need more help write

Thanks for pointing that out , I changed it but the problem still exists.

Robin2: Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. Notice how they don't rely on delay().

It would be a big help if you could describe how your program is supposed to work - i.e. a walk-through of the code.

The data you send in ACK and NAK looks like it could be figured out while you are writing the program and included as a pre-defined byte array

...R

The incoming data is 7 bytes

Byte 1 = 0xAF -- Header Byte 2 = 0x1F -- Header Byte 3 = DID_H -- Device ID High byte Byte 4 = DID_L -- Device ID Low Byte Byte 5 = 0x11 -- Direction - 0x11 is server to client - 0x22 is client to server Byte 6 = CMD -- commands (see function execute in the code) Byte 7 = CRC -- bytes 1 to 6 Xor'd - this is to check if incoming data is valid

the arduino pro mini receives the 7 bytes -> executes the command -> sends ACK

if the command is not in the list it sends NAK

the data is structured this way because if i wanted to add another device on the network this will allow me to add it

Thanks

Check the rest of your code for the same issue - I found two more.

void ACK()
{
  byte ack[6];
  ack[0] = 0xAF;
  ack[1] = 0x1F;
  ack[2] = DID_H;
  ack[3] = DID_L;
  ack[4] = 0x22;
  ack[5] = 0xAA;
  byte crc = 0x00;
  for(int i=0;i<=5;i++)
  {
    crc ^= ack[i];
  }
  ack[6] = crc;                        // <=== overflow
  zb.write(ack,sizeof(ack));
}



void NAK()
{
  byte ack[6];
  ack[0] = 0xAF;
  ack[1] = 0x1F;
  ack[2] = DID_H;
  ack[3] = DID_L;
  ack[4] = 0x22;
  ack[5] = 0xFF;
  byte crc = 0x00;
  for(int i=0;i<=5;i++)
  {
    crc ^= ack[i];
  }
  ack[6] = crc;                       // <=== overflow
  zb.write(ack,sizeof(ack));
}

Thank you very much
This fixed my problem :slight_smile:

aster94:
In my opinion you should use a “bloking” condition before every read()

I presume you mean “blocking”

There should be NO blocking code anywhere in an Arduino program.

…R