Arduino freeze - error in the code?

Hi everybody,

Seems my arduino is randomly freezing (orange “send” led statut stay switch on instead of blinking) with this code inside, I tested with an other arduino, same issue, any idea ?

const int magicPin = 3;
const int variateurPin = 8;
const int batteriePin = 9;
const int laserAvPin = 10;
const int laserArPin = 11;

boolean variateur;
boolean batterie;
boolean laserAv;
boolean laserAr;
boolean magic;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  pinMode(variateurPin, INPUT); 
  pinMode(batteriePin, INPUT);
  pinMode(laserAvPin, INPUT); 
  pinMode(laserArPin, INPUT);
  pinMode(magicPin, INPUT); 
}

void loop() {

     
      variateur = digitalRead(variateurPin);
      batterie  = digitalRead(batteriePin);
      laserAv   = digitalRead(laserAvPin);
      laserAr   = digitalRead(laserArPin);
      magic   = digitalRead(magicPin);
      
      //concatenation
      byte bit1 = variateur;
      byte bit2 = batterie;
      byte bit3 = laserAv;
      byte bit4 = laserAr;
      byte bit5 = magic;
     
      byte byteaenvoyer = bit1 | bit2 << 1 | bit3 << 2 | bit4 << 3 | bit5 << 4;
      
      Serial.println(byteaenvoyer, DEC);


      delay(200);

}

Thanks by advance for your help

boolean variateur;
boolean batterie;
boolean laserAv;
boolean laserAr;
boolean magic;

      variateur = digitalRead(variateurPin);
      batterie  = digitalRead(batteriePin);
      laserAv   = digitalRead(laserAvPin);
      laserAr   = digitalRead(laserArPin);
      magic   = digitalRead(magicPin);

The digitalRead() function does not return a boolean. Why are you using a boolean to store the result?

Why does the return value need to be stored in a global variable?

      byte bit1 = variateur;
      byte bit2 = batterie;
      byte bit3 = laserAv;
      byte bit4 = laserAr;
      byte bit5 = magic;

Why do you need to make copies of the global variables? Why are you copying to a different type?

      byte byteaenvoyer = bit1 | bit2 << 1 | bit3 << 2 | bit4 << 3 | bit5 << 4;

Do you KNOW the precedence of all of the operators involved in this statement? If not, where are the parentheses?

      Serial.println(byteaenvoyer, DEC);

Why would you print a binary value in base 10?

orange “send” led statut stay switch on

What “orange send led status”?

Hi PaulS,

First, thanks a lot for your quick reply.

My goal with this code is to send 5 digital input state in 1 byte.
For example if :
digital input 1 = HIGH (1)
digital input 2 = LOW (0)
digital input 3 = LOW (0)
digital input 4 = HIGH (1)
digital input 5 = HIGH (1)
I want to send 1 byte (8bits) :
0000 10011 (Binary)
So : 19 (DEC)

But I’m not skill enought to find and correct my error.
Let’s try to learn from my error…:slight_smile:

The digitalRead() function does not return a boolean. Why are you using a boolean to store the result?

I was thinking it does, like HIGH=1 and LOW=0. But of course you are right, according to the references, it seems it return just HIGH and LOW. How would you convert this HIGH and LOW state to 0 and 1?

Why do you need to make copies of the global variables? Why are you copying to a different type?

The idea was to “convert” the boolean value (0) or (1) to a byte.
Example 0 = 0000 0000 and 1 = 0000 0001

Do you KNOW the precedence of all of the operators involved in this statement? If not, where are the parentheses?

No I dont, actually I try to adapt something I found on the net… But it seems to work, bitshift seems to have a higher precedence than the OR operator.
Should I write that instead ? :

 byte byteaenvoyer = bit1 | (bit2 << 1) | (bit3 << 2) | (bit4 << 3) | (bit5 << 4);

Why would you print a binary value in base 10?

Because in my application on the computer, I have a simple function to extract bits (00001001) for the decimal value (19).

What “orange send led status”?

Sorry I mean the Serial Transmit orange led (Tx),

I hope I aswer all your question, sorry I should have been more precise in my first post.

I was thinking it does, like HIGH=1 and LOW=0. But of course you are right, according to the references, it seems it return just HIGH and LOW. How would you convert this HIGH and LOW state to 0 and 1?

HIGH is a name that corresponds to a value of 1. LOW is a name that corresponds to the value 0. There is no conversion needed.

The idea was to "convert" the boolean value (0) or (1) to a byte.

There is no need to "convert" anything by making a copy in a different data type variable.

Should I write that instead ?

Yes.

You have some code that does something. You have not explained what the code actually does. You apparently have some problem, or you wouldn't have posted here. You have not explained what that problem is.

You may need a longer delay, to allow one value to be sent before you start sending the next. Once you've got the byte of interest, it seems unnecessary to convert that value to a string and then need to convert the string back to a value on the other end (whatever that other end is).

I have a simple function to extract bits (00001001) for the decimal value (19).

?

I think the problem is very simple - the Arduino doesn't do magic.

Slightly more seriously, please explain what the program is supposed to do so that we can understand it in its proper context.

Also, what is supplying the inpots and what is receiving the data that is sent using Serial.println().

It's not elegant but you shouldn't have any problem reading digitalRead() into a boolean variable.

...R

Hi PaulS, Awol, and Robin2, thanks again,

There is no conversion needed

There is no need to “convert” anything by making a copy in a different data type variable.

Ok I get it. You mean I can make bitwise and bitshift operation on any variable, of any data type ?
But then what is the best data type to choose in my code? I suppose it’s the one which consume less memory from the arduino ? Then why boolean is not a good data type ?

Let say I use byte data type, so this code should be less redundant ?:

const int magicPin = 3;
const int variateurPin = 8;
const int batteriePin = 9;
const int laserAvPin = 10;
const int laserArPin = 11;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  pinMode(variateurPin, INPUT); 
  pinMode(batteriePin, INPUT);
  pinMode(laserAvPin, INPUT); 
  pinMode(laserArPin, INPUT);
  pinMode(magicPin, INPUT); 
}

void loop() {
      
      //concatenation
      byte bit1 = digitalRead(variateurPin);
      byte bit2 = digitalRead(batteriePin);
      byte bit3 = digitalRead(laserAvPin);
      byte bit4 = digitalRead(laserArPin);
      byte bit5 = digitalRead(magicPin);
     
      byte byteaenvoyer = bit1 | (bit2 << 1) | (bit3 << 2) | (bit4 << 3) | (bit5 << 4);
      
      Serial.println(byteaenvoyer, DEC);

      delay(300);

}

I have a simple function to extract bits (00001001) for the decimal value (19).

Could you please be more precise and explain why do you quote this ?
On my program, I receive DEC value as expected from the arduino (19 in my example), Then I use a function call BIT, which accept decimal value as input, as argument I ask the first 8 bits, and the function return 8 boolean variable giving the state of each bit.
So I have the state of each input of the arduino.

it seems unnecessary to convert that value to a string and then need to convert the string back to a value on the other end

Humm how would you do ? What would you send from the arduino? Sorry I’m learning…

please explain what the program is supposed to do so that we can understand it in its proper context.

Sorry I didnt did that at first to avoid a too long post. I’m just trying to receive informations from a high power motor speed driver as fast as possible. This industrial motor speed driver has digital output which return info about it and sensors connected to it.
For my project, I want to link the motor movement and sensor data to sound effects. So I need to send info as soon as possible to avoid any delay between sound and movements.
The idea was to reduce datas to one byte and try to send them as fast as possible.
I will increase the baud rate, but as I do that in an experimental and learning purpose, I would like to make sure my code is ok at first at 9600, it should work anyway.

what is supplying the inputs

The speed driver has five 24V digital output, I connect those output to relays, and I connet the arduino input to those relay. (dry contact)

what is receiving the data that is sent using Serial.println()

A computer, and I’m using visual programing software call vvvv (see vvvv.org). This sofware will allow me to play sound and video according to arduino input. It is based on C#. I has a quite simple to use function to get datas from a COM port as same as arduino IDE serial monitor do.

You have not explained what that problem is.

As I explain, the problem is quite simple, all is working well, I receive datas correctly, but sometime the arduino “freeze”, I mean, I dont receive data anymore, and the TX orange led on the board stop blinking, and stay on instead.

You may need a longer delay

Does this can cause the “freezing” problem?
I will try with the new code and 300ms delay

Thanks for your help :slight_smile:

Quote I have a simple function to extract bits (00001001) for the decimal value (19). Could you please be more precise and explain why do you quote this ?

I quoted it because a) 00001001 I interpreted as an octal number, with the decimal value 513 b) If you meant the representation as binary, it has the decimal value 9, not 19.

The speed driver has five 24V digital output, I connect those output to relays, and I connet the arduino input to those relay. (dry contact)

This looks like the starting place.

First, a hardware comment.

I think you mean that the 24v signals cause relays to switch on an off and the relay output is used to toggle the Arduino I/O pins. You say you want a fast response but relays are not fast. Wouldn't it be much better just to use a pair of resistors on each output to divide the voltage down below 5v?

Now to the software.

If there are 5 signals presumably you only get a 5 bit input to the Arduino? - that's what your Reply #2 seems to imply.

What Arduino are you using? If you are using an Uno (a Mega would make things easier) you should arrange to connect your 5 inputs to I/O pins 8 to 12 (8 being the least significant bit). Then you can read them all into a byte with a single instruction

byte myByte = PINB;

The upper bits of the byte - bits 5, 6 and 7 will have irrelevant data in them and you can convert those to zeros with

myByte |= 0b000111111;

Job done!

...R

Awol : Yes i was thinking of binary representation, and yes 00001001(BIN) is 9 (DEC) ... sorry

Robin2 :

relays are not fast

use a pair of resistors on each output to divide the voltage down below 5v

Thanks for the tip, It will surely avoid me to waste time ! I'll still continue my test with the relay, this way I can be sure that my "freezing" issue is not coming from hardware part.

I'm using an arduino uno.

Sorry I dont get the end or you post : - Why I should use a mega? - Why I should arrange my input to 8 to 12, what is this single instruction byte myByte = PINB; you are speaking about? - Why The upper bits of the byte - bits 5, 6 and 7 will have irrelevant data? - Why do you write 0b000111111 and not just 00111111 is it the way to write binary ?

I'm really interested in learning thoses points, sorry for thoses newbie questions, Thanks in advance.

Why do you write 0b000111111 and not just 00111111 is it the way to write binary ?

Because numbers prefixed with a zero are interpreted as octal. "0b" tells the compiler your literal is binary.

Thanks Awol.

Robin2,
Maybe I get it, not sure,
Arrange the input from 8 to 12 allows me to make a loop, is it the reason why you advice me that ?

Then should I write this ? :

void setup() {
  Serial.begin(9600);
  for (int i = 8; i < 12; i++)  {
    pinMode(i, INPUT);      
  }
}

void loop() {
      
      byte myByte[5];
      
      for (int i = 0; i < 5; i++) { 
      myByte[i] = digitalRead(i+8); // Read input
      myByte[i] |= B00111111;       // Clean irrelevant data
      }

     //concatenation
      byte myByteToSend = myByte[0] | (myByte[1] << 1) | (myByte[2] << 2) | (myByte[3] << 3) | (myByte[4] << 4);
      
      Serial.println(myByteToSend, DEC);

      delay(300);

}

I change 0b000111111 to B00111111 according to the example here :
http://arduino.cc/en/Reference/BitwiseCompoundOr

Or is it because there is a special behaviour with input 5,6 and 7? Does the irrelevant data you are speaking about are the reason of my problem?

I change 0b000111111 to B00111111 according to the example here

I'd change it back - the "B" prefix isn't portable and is only valid for up to 8 bits.

rogerlette: Arrange the input from 8 to 12 allows me to make a loop, is it the reason why you advice me that ?

NO, not at all. I mean connect your wires to pins 8 to 12 which are bits 0 to 4 of PORTB.

You can read all of the bits (pins) in PORTB at the same time with the instruction PINB. The upper bits of the byte - bits 5, 6 and 7 will have irrelevant data in them so you need to convert those to zeros. These two lines of code read ALL 5 of your pins and present the value as a byte. (Always assuming I understand what you are trying to do). Try it and see by adding Serial.println(myByte, BIN);

byte myByte = PINB;
myByte |= 0b000111111;

There is no need for any FOR loop.

By the way PINB is short for Port IN B.

...R