How does my program break this while loop??

I have one slave (Arduino Uno) and one master (MKR1000) communicating over I2C. The Master is sending simple int variables to command the slave, using this code to listen for a command:

void receive_I2C_Event(int) {
while (Wire.available()) { // loop gjennom alle tegn
c = Wire.read(); // motta tegn som byte
Serial.println(c); // print tegnet på serieportenr
if (c == 1) {
w_Fremover = true; // Sender kommando om å kjøre båten fremoover
}
if (c == 3){
a_Venstre = true;
}
if (c == 4){
d_Hoyre = true;
}
if (c == 6){
s_Bakover = true;
}
if (c== 7){
p_Party = true;
}
if (c== 2){
stopp = true;
}
if (c== 5){
brems = true;
}

Here comes the big question! This code is all attached to the slave. The slave is a robot rowing an oar on a boat. When the w_Fremover = true, the boat is rowing forward inside the do while. But when i change the
"c" variable into something that does not match the "do while" conditions, it stops the "do while". But how on earth does the code know that i change the "c variable" when the software is still inside the do while?!

void loop() {

digitalWrite(LEDR,HIGH);
digitalWrite(LEDG,HIGH);

if(w_Fremover)
{

servoHev.write(vinkelHev1);
delay(speed);
servoRo.write(vinkelRo2);
delay(speed);

do {
w_Fremover=false;
Serial.println("Båten går fremover en gang");
servoHev.write(vinkelHev2);
delay(speed);
servoRo.write(vinkelRo1); // hev 1 er opp
delay(speed);
servoHev.write(vinkelHev1);
delay(speed);
servoRo.write(vinkelRo2); // hev 2 er opp
delay(speed);
} while (c == 1 || c == 8 || c == 9);

}

if(c==8){ //øker hastighet --> minker delay
speed-=100;
w_Fremover = true;
Side 5
}
if(c==9){ //minker hastighet --> øker delay
speed+=100;
w_Fremover = true;
}


Regards Pokerdaniel4

Please post your code (all of it) in code tags.

It doesn't, unless you call receive_I2C_Event(int) inside do..while loop.

Complete code from master and slave. We control the boat from a browser, please look file.

Please see reply #1

Here is all of the code. The do…while breaks if I change the c variable! So… Is there some sort of multi threading in Arduino??

Master_code.pdf (85.1 KB)

Slave_left_code.pdf (94.6 KB)

pokerdaniel4:
Here is all of the code. The do..while breaks if I change the c variable! So... Is there some sort of multi threading in Arduino??

Nope, no multithreading so you need to plan your code properly.

Why do you refuse the code tags?

I posted the code in PDF files. Cant you see it?

I posted the code in PDF files

Why? Are code tags too difficult?

pokerdaniel4:
I posted the code in PDF files. Cant you see it?

Many people can't. A lot more won't even bother.

Please attach your .ino files or, if the code is short enough, just include it in your next Reply.

I am not going to waste my time downloading a PDF file and then extracting the text from it so I can view it in my text editor.

Help us to help you.

...R

I would love to put it in tags, but the whole code is too long, I receive this error message: "The message exceeds the maximum allowed length (9000 characters)."

void loop() {

  digitalWrite(LEDR,HIGH);
  digitalWrite(LEDG,HIGH);

  if(w_Fremover)
  {

    servoHev.write(vinkelHev1);
    delay(speed);
    servoRo.write(vinkelRo2);
    delay(speed);
    
    do {
    w_Fremover=false;
    Serial.println("Båten går fremover en gang");  
    servoHev.write(vinkelHev2);
    delay(speed);
    servoRo.write(vinkelRo1); // hev 1 er opp
    delay(speed);
    servoHev.write(vinkelHev1);
    delay(speed);
    servoRo.write(vinkelRo2); // hev 2 er opp
    delay(speed);
    } while (c == 1 || c == 8 || c == 9);
    
  }


    if(c==8){  //øker hastighet --> minker delay
      speed-=100;
      w_Fremover = true;
Side 5
}
    if(c==9){  //minker hastighet --> øker delay
      speed+=100;
      w_Fremover = true;
      }


void receive_I2C_Event(int) {
  while (Wire.available())  { // loop gjennom alle tegn
    c = Wire.read();          // motta tegn som byte
    Serial.println(c);          // print tegnet på serieportenr
    if (c == 1) {
      w_Fremover = true;  // Sender kommando om å kjøre båten fremoover
    }
    if (c == 3){
      a_Venstre = true;
}
if (c == 4){
      d_Hoyre = true;
    }
    if (c == 6){
      s_Bakover = true;
}
if (c== 7){
      p_Party = true;
    }
    if (c== 2){
      stopp = true;
}
if (c== 5){
      brems = true;
    }

Robin2:
Please attach your .ino files or, if the code is short enough, just include it in your next Reply.

OP:
Those instructions seemed pretty clear to me. Which part didn’t you understand?

Here are the .ino files.

Venstre.ino (5.24 KB)

test-master.ino (16 KB)

I am not an expert on I2C but I reckon you should remove most of that code from the function receive_I2C_Event() and just use the function to collect the I2C data and save it somewhere for use by code in a different function. That way the receive_I2C_Event() function can terminate quickly.

...R

I am not sure if you understand my question, because my code works fine... By changing the value of the c variable outside the Do While it hops out of the Do While because it no longer matches the conditions of the Do While. This should NOT work, but it does. The Arduino Uno realise that the C variable is being changed outside the Do While, so it breaks and starts another Do While.

Does anyone know why this happens? It is just out of curiosity...

use ' else if ' instead.

if (c == 1) {
w_Fremover = true; // Sender kommando om å kjøre båten fremoover
}
else if (c == 3) {
a_Venstre = true;
}
else if (c == 4) {
d_Hoyre = true;
}
else if (c == 6) {
s_Bakover = true;
}
else if (c == 7) {
p_Party = true;
}
else if (c == 2) {
stopp = true;
}
else if (c == 5) {
brems = true;
}

pokerdaniel4:
Does anyone know why this happens? It is just out of curiosity...

Because your 'c' variable has global scope and you're changing it inside the 'receive_I2C_Event()' function. This is a callback function that gets called by the I2C ISR. It runs asynchronously to your 'loop()' function. It can run (and change the value of 'c') at any time.

Oh, thank you very much! This cleared things up for me!

So you are saying there is a ISR method in the library somewhere? Only working with external hardware devices?

"Interrupt Service Routine." An ISR (also called an interrupt handler) is a software process invoked by an interrupt request from a hardware device. It handles the request and sends it to the CPU, interrupting the active process. When the ISR is complete, the process is resumed.

So this is how it works, right?

  Wire.begin();
  Wire.beginTransmission(0x48);             // connect to DS1621 (#0)
  Wire.write(0xAC);                            // Access Config
  Wire.write(0x02);                            // set for continuous conversion
  Wire.beginTransmission(0x48);             // restart
  Wire.write(0xEE);                            // start conversions
  Wire.endTransmission();

This doesn't look right. You need another Wire.endTransmission() after Wire.write(0x02), otherwise the access config command won't be sent.

Pete