Serial Triggering on Slave Arduino

Hay all, new here and this is my first post. If I have made any mistakes in posting please provide corrections and be gentle ;).

So here is my question... or problem I am experiencing. I am trying to make a L0LA droid. It has an accelerometer which triggers wing movement via 2 sg90 servos, this just fine. I also want it to play some sounds (via tones) while it is moving its wings. I have found that I cannot simultaneously flap wings while generating sounds, so I have introduced an additional nano to operate sound while the main nano operates its wing. I have done this through the serial.write/read function on the tx/rx side of things. I have an idle function that works great, however, while it is moving i am trying to trigger the slave nano to "speak" but it keeps getting interrupted (starts to play a tone and then gets cut off). I have been working on this problem for two days now and i am no closer to figuring this out.

So, my question is, why do my tones keep getting interrupted and how do I go about fixing this?

Master Nano code

void balance(){                               //function called when movement is detected by accelerometer
  float accX = mpu.getAccX();       // setting a variable to acc measurement 
    if(accX>.01||accX<-.01){          //if measurement is detected outside -.01 to .01 
    balanceTimer++;                       // add to my balance timer 
    }
    if(balanceTimer >= balanceTimerSet){    //if balance timer is greater than the set 
      talk();                                                            // do the talk function 
      delay(10);                                                    // tried to see if delay would help and it does not 
      balanceTimer = 0;                                     //reset timer and balance timer (originally set to 0)
      balanceTimerSet = 15;
    }
  if(accX>0.1){                                                    //this is all wing movement  and LEDs 
    lWing.easeTo(lwaClosed, sensitivity);
    rWing.easeTo((accX)*rwaRange,sensitivity);
    leds[0] = CRGB :: Purple;
    FastLED.show();
    }     else if(accX<-0.1){
          rWing.easeTo(rwaClosed, sensitivity);
          lWing.easeTo(lwaClosed+(accX*lwaRange), sensitivity);
          leds[0] = CRGB :: Blue;
          FastLED.show();
          }    else{
               idle();
               } 
      Serial.println(balanceTimer);
}

void idle(){                                                            // while just sitting with no movement same as above 
  rWing.easeTo(rwaClosed, sensitivity);
  lWing.easeTo(lwaClosed, sensitivity);

      idleTimer++;
  if (idleTimer >= 50){
 //   Serial.println("sending idle Byte");
    delay(10);
    talk();
    idleSetTime = random(50,1000);
    idleTimer = 0;
    }
}

void talk(){                                              //talk function 
  motion = 1;                                //eventually will have different case and this will be set when called 
  Serial.write(motion);                //send signal to slave nano
  delay(10);                                   //though a delay would help, it did not
  //  Serial.println("byte sent");
}

slave nano

void loop() {
    Serial.println(Serial.available());
  
  if(Serial.available()>0){

         if(!soundPlaying){   //tried adding a bool while it was playing but it still doesn't work
            soundPlaying = true;
            playSound();
          }
     }
}


void playSound(){                      //this is all just the sounds

    int K = 2000;
    switch (random(1,7)) {
        
        case 1:phrase1(); break;
        case 2:phrase2(); break;
        case 3:phrase1(); phrase2(); break;
        case 4:phrase1(); phrase2(); phrase1();break;
        case 5:phrase1(); phrase2(); phrase1(); phrase2(); phrase1();break;
        case 6:phrase2(); phrase1(); phrase2(); break;
    }
    for (int i = 0; i <= random(3, 9); i++){
        
        tone(speakerPin, K + random(-1700, 2000));          
        delay(random(70, 170));             
        noTone(speakerPin);         
        delay(random(0, 30));             
    } 
    noTone(speakerPin);         
    delay(random(2000, 4000));   
   soundPlaying = false; 
}
void phrase1() {
    
    int k = random(750,1500);
    for (int i = 0; i <=  random(100,2000); i++){
        
        tone(speakerPin, k+(-i*2));          
        delay(random(.9,2));             
    }  
    for (int i = 0; i <= random(100,1000); i++){
        
        tone(speakerPin, k + (i * 10));          
        delay(random(.9,2));             
    } 
     soundPlaying = false; 
}

void phrase2() {
    
    int k = random(750,2000); 
    for (int i = 0; i <= random(100,2000); i++){
        
        tone(speakerPin, k+(i*2));          
        delay(random(.9,2));             
    }    
    for (int i = 0; i <= random(100,1000); i++){
        
        tone(speakerPin, k + (-i * 10));          
        delay(random(.9,2));             
    } 

}

Again the idle works as expected plays a series of beeps and boops every few seconds, but as soon as i start moving it, it will start to play but seems to get cut off. Again, any help is greatly appreciated!

-JMo

Well, you asked, so... Please read:
How to get the best
Then please post a schematic, and perhaps a picture of your setup. You did very well by posting your code correctly right out of the gate, and you may be absolutely correct in suspecting only your software, but you'd be surprised at how many new posters have fundamental circuit errors hiding behind 'a software problem'.
And, belatedly, Welcome! This place can get a little 'tense', but overall those who answer you will be trying to help you, so please give them some help as they help you!

In this instance, I particularly suspect your power setup, esp. with respect to the servos, so we need to see that wiring.

thank you for the reply! I will get some schematics put up here shortly so you can see what I am dealing with. I will try and make them as readable as possible...

Uploaded schematic as requested. Again, thank you for your help.

Ok. Right off the bat, You MUST not power a Nano via Vin with 5V. Vin must be at least 7 VDC. So, your slave behavior must be suspect. Power it by supplying the Nano with 5V connected to the 5V pin, as it's an in/out pin.
It looks like you're trying to run all this off the 5V power from one USB port. That's bad. Read on.
Your individual servo's specs will vary, but typically SG90's have a spec similar to this:
Typical hobby servo

Spec's from that page:
Electrical Specification (Function of the Performance): Operating speed (at no load): 0.09±0.01 sec/60°(4.8V ) 0.08±0.01 sec/60°(6V)
Running current (at no load): 400±30mA (4.8V ) 500±30mA(6V)
Stall torque (at locked): 2.0±0.20kg·cm (4.8V ) 2.2±0.20kg·cm(6V)
Stall current (at locked): 1300±40mA (4.8V ) 1600±50mA(6v)
Idle current (at stopped): 6±1mA (4.8V ) 6±1mA(6v)
Running life(at no load): >350000 Turns(4.8V ) >320000 Turns(4.8V )
Here's a little explanation of that tech stuff:

  1. Idle current - when your servo reaches the end of travel by achieving it's setpoint, you will then draw the 'idle' current. If all your servos are perfectly aligned, this can be measured for one servo and multiplied by the number of servos to get a baseline minimum operating current - but it's more or less irrelevant, as other worst-case numbers are much larger.

  2. Operating current - usually, stated operating current is "no load" - literally, with no plastic horns even, but certainly with no coupling to any mechanical/physical process. That's the 450 mA (ish) above, once the servo is moving at the "Operating speed"; any resistance to movement increases this value.

  3. Stall current - if your servo perchance moves ends in 'stall', i.e. pushing up against something because you told it to go to 92 degrees, but it's stuck at 91 trying to get there, then you've got a servo in 'stall' until the next time you move it. This is BAD, but can be guarded against if your code turns off the servo because it "thinks it's there".

  4. Starting current - When a servo starts moving, the current surge is very large. Starting current is usually close to stall current, but decays away as the device starts moving (whereas stall current doesn't); but, if you try to move too slowly, for example in 1 degree steps with too much delay between steps(see the 'sweep' example in the Arduino IDE, change it's delays to 100 or more ms per step), you can actually have that starting surge repeatedly during a move, as the servo 'jitters' from A to B. So, 1350 mA more or less for this servo to start from rest.

So you see, you need a very hefty 5V supply for your servo setup(the info above relates to one servo, so multiply the current needs by 2); the Arduino is utterly incapable of handling this, and most USB ports don't like it much either.
I would avoid drawing any conclusions from your software results until you've addressed the power issue. What you need is a 5VDC, 2(min) or 3(good) ampere power supply.

THANK YOU! I rewired my setup, the plan was to run this all off a 7V Li-ion battery, so i hooked that up, ran all the servo vcc lines directly there (specs say these servos can handle 7.2V), common ground along them and both nanos. Everything is working fantastically! You were absolutely right, and thinking back it makes sense on some of the other issues i was having (i thought my usb cord was damaged because the serial to my computer kept losing connection, turns out, i didnt have enough juice to keep it going).

you'd be surprised at how many new posters have fundamental circuit errors hiding behind 'a software problem'.

you were correct there as well! Again thank you!

-JMo

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.