Programming a string of commands simply for kids

Hi all,

I'm a science teacher and curious maker who did some boe-bot and arduino coding years ago. I keep thinking up projects my kids get into and I want to help them (7 yo, 9 yo, 13 yo) understand the coding side more... but my knowledge is limited.

Right now we are trying to use an Arduino Uno and a L298N to run a pair of dc motors that will eventually serve as a remote control car/robot/whatever they want...

I've been using the code below and understand the logic of the code, and the circuit pretty well.

int motor1pin1 = 2;
int motor1pin2 = 3;

int motor2pin1 = 4;
int motor2pin2 = 5;

int LED = 13;

void setup() {
  // put your setup code here, to run once:
  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:   
  digitalWrite(motor1pin1, HIGH);
  digitalWrite(motor1pin2, LOW);

  digitalWrite(motor2pin1, HIGH);
  digitalWrite(motor2pin2, LOW);
  delay(1000);

  digitalWrite(LED, HIGH);
  delay(500);
  
  digitalWrite(LED, LOW);
  delay(500);
  
  digitalWrite(motor1pin1, LOW);
  digitalWrite(motor1pin2, HIGH);

  digitalWrite(motor2pin1, LOW);
  digitalWrite(motor2pin2, HIGH);
  delay(1000);
}

But the code is a little cumbersome for the 7 and 9 yo's to understand. Is there a way to define the 4 pin states with one word? That way when we want to go back and edit the program we can use commands like "forward" or "backward" with delays etc...
They are familiar with scratch coding and cod-a-pillar, so I thought this would be a good way to transition them into arduino.

For instance:

#define Forward = digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);
              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);

When I tried the above, it unsurprisingly didn't work. I'm not even sure what this process might be called, short-handing? Am I trying to write a very simple library?

Any help or guidance is appreciated!
-Mike

Schematic:

Read about functions, a bit like ‘subroutines’.

Thank you!

Knowing what to look for -- "function" -- and learning the syntax was all it took.
I'm so grateful for this community!

I feel the same way. I like to put the cumbersome code into functions, then call the function I need. Here is an example of driving a DC motor. You can see in setup() where I call the function eightSteeringModes() which then uses a list of functions to call the individual steering mode.

And here is a hands-on sketch... (1) remove all connections (2) put one jumper wire in a ground pin (3) upload the sketch (4) touch a DIO or Analog pin and you will see the pin in the Serial Monitor. Do not touch Vcc, Reset or Vin.

If your kids are really interested in learning to code they will teach themselves if you give them the computer and boards to play with. One of my friends is a very good self taught developer and all round computer and network expert, all from his parents giving him a ZX Spectrum when he was 8. If they are interested they will learn, if not then find something else that interests them.

Did you fall asleep on your 'post' button?

2 Likes

No, I kept getting an error every time I posted the reply. Duplicate replies deleted, thanks for telling me. With apologies to @vogtm2 .
(To explain, I replied with the same response 5 times. Ooops!)

you may be interested in the following, which i customize for each program i write to exercise and debug

it processes single letter commands preceded by a #. multiple commands can be entered.

for example, 13O configures the builtin LED as an output. 13s would set the pin HIGH turning it on and 13c set the pin LOW

it allows executing the various I/O functions (e.g. pinMode(), digitalWrite()) without having to recompile/reload code, helping someone understand what they do without taking the time edit/compile/reload

you can add new commands such as the multiple digitalWrites to initialize the motor pins and drive the motors, change speed, forward/reverse.

once they understand what the I/O functions do, they can try writing programs that use them directly

// pcRead - debugging using serial monitor

const char version [] = "PcRead 240209a";

int debug = 0;

// -----------------------------------------------------------------------------
// process single character commands from the PC
#define MAX_CHAR  10
char s [MAX_CHAR] = {};

int  analogPin = 0;

void
pcRead (void)
{

    static int  val = 0;

    if (Serial.available()) {
        int c = Serial.read ();

        switch (c)  {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            val = c - '0' + (10 * val);
            break;

        case 'A':
            analogPin = val;
            Serial.print   ("analogPin = ");
            Serial.println (val);
            val = 0;
            break;

        case 'D':
            debug ^= 1;
            break;

        case 'I':
            pinMode (val, INPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT");
            val = 0;
            break;

        case 'O':
            pinMode (val, OUTPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" OUTPUT");
            val = 0;
            break;

        case 'P':
            pinMode (val, INPUT_PULLUP);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT_PULLUP");
            val = 0;
            break;


        case 'a':
            Serial.print   ("analogRead: ");
            Serial.println (analogRead (val));
            val = 0;
            break;

        case 'c':
            digitalWrite (val, LOW);
            Serial.print   ("digitalWrite: LOW  ");
            Serial.println (val);
            val = 0;
            break;

        case 'p':
#if !defined(ARDUINO_ARCH_ESP32)
            analogWrite (analogPin, val);
            Serial.print   ("analogWrite: pin ");
            Serial.print   (analogPin);
            Serial.print   (", ");
            Serial.println (val);
            val = 0;
#endif
            break;

        case 'r':
            Serial.print   ("digitalRead: pin ");
            Serial.print   (val);
            Serial.print   (", ");
            Serial.println (digitalRead (val));
            val = 0;
            break;

        case 's':
            digitalWrite (val, HIGH);
            Serial.print   ("digitalWrite: HIGH ");
            Serial.println (val);
            val = 0;
            break;

        case 't':
            Serial.print   ("pinToggle ");
            Serial.println (val);
            digitalWrite (val, ! digitalRead (val));
            val = 0;
            break;

        case 'v':
            Serial.print ("\nversion: ");
            Serial.println (version);
            break;

        case '\n':          // ignore
            break;

        case '?':
            Serial.println ("\npcRead:\n");
            Serial.println ("    [0-9] append to #");
            Serial.println ("  # A - set analog pin #");
            Serial.println ("  # D - set debug to #");
            Serial.println ("  # I - set pin # to INPUT");
            Serial.println ("  # O - set pin # to OUTPUT");
            Serial.println ("  # P - set pin # to INPUT_PULLUP");
            Serial.println ("  # a - analogRead (pin #)");
            Serial.println ("  # c - digitalWrite (pin #, LOW)");
            Serial.println ("  # p - analogWrite (analogPin, #)");
            Serial.println ("  # r - digitalRead (pin #)");
            Serial.println ("  # s  - digitalWrite (pin #, HIGH)");
            Serial.println ("    t  - toggle pin output");
            Serial.println ("    v  - print version");
            Serial.println ("    ?  - list of commands");
            break;

        default:
            Serial.print ("unknown char ");
            Serial.println (c,HEX);
            break;
        }
    }
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    pcRead ();
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin(9600);

    Serial.println (version);
#if defined(ARDUINO_ARCH_ESP32)
    Serial.println ("esp32");
#endif
}
1 Like

Thanks for that thought! They are not interested yet, but as a teacher I've found kids usually get interested after a glimpse of possibility! I suppose at this point I am still helping them realize that things do not need to be black boxes.

Thanks!
It's going to take me a bit to wrap my head around this method, but I think I can see its value.

Thanks for sharing these examples.
I didn't know about the Arduino simulator either! This might help me save on batteries!

OK, Posting for two reasons. 1. It's fun to share where we are now, and 2. Always open for advice on better/more efficient ways to code!

So, we've been having fun sending our little robot crashing blindly into things using the following code.

/* For a robot with two brushed dc motors and L298N motor driver

*/

int motor1pin1 = 2;
int motor1pin2 = 3;

int motor2pin1 = 4;
int motor2pin2 = 5;

int Forward(){
              digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);
} 

int Stop(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, LOW);
}

int Reverse(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, HIGH);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, HIGH);
}

int Right(){
            digitalWrite(motor1pin1, HIGH);
            digitalWrite(motor1pin2, LOW);

            digitalWrite(motor2pin1, LOW);
            digitalWrite(motor2pin2, HIGH);
}

int Left(){
            digitalWrite(motor1pin1, LOW);
            digitalWrite(motor1pin2, HIGH);

            digitalWrite(motor2pin1, HIGH);
            digitalWrite(motor2pin2, LOW);  
}

void setup() {
  // put your setup code here, to run once:
  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:   
  Reverse();
  delay(2000);
  
  Stop();
  delay(500);
  
  Right();
  delay(750);
  
  Stop();
  delay(500);

  Reverse();
  delay(2000);
  
  Stop();
  delay(500);
  
  Left();
  delay(750);

  Stop();
  delay(500);
  
}

Then we tried an IR receiver to decode a remote control so we could change the robot's motion with the remote using If/Else with the following code.

#include <Arduino.h>

/*
 * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
 */
#include "PinDefinitionsAndMore.h"
#include <IRremote.hpp> // include the library


int motor1pin1 = 2;
int motor1pin2 = 3;

int motor2pin1 = 4;
int motor2pin2 = 5;

int Forward(){
              digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);
} 

int Stop(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, LOW);
}

int Reverse(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, HIGH);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, HIGH);
}

int Right(){
            digitalWrite(motor1pin1, HIGH);
            digitalWrite(motor1pin2, LOW);

            digitalWrite(motor2pin1, LOW);
            digitalWrite(motor2pin2, HIGH);
}

int Left(){
            digitalWrite(motor1pin1, LOW);
            digitalWrite(motor1pin2, HIGH);

            digitalWrite(motor2pin1, HIGH);
            digitalWrite(motor2pin2, LOW);  
}

void setup() {

  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);
    
    Serial.begin(115200);
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    printActiveIRProtocols(&Serial);
    Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}

void loop() {
    /*
     * Check if received data is available and if yes, try to decode it.
     * Decoded result is in the IrReceiver.decodedIRData structure.
     *
     * E.g. command is in IrReceiver.decodedIRData.command
     * address is in command is in IrReceiver.decodedIRData.address
     * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
     */
    if (IrReceiver.decode()) {

        /*
         * Print a summary of received data
         */
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
            // We have an unknown protocol here, print extended info
            IrReceiver.printIRResultRawFormatted(&Serial, true);
            IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
        } else {
            IrReceiver.resume(); // Early enable receiving of the next IR frame
            IrReceiver.printIRResultShort(&Serial);
            IrReceiver.printIRSendUsage(&Serial);
        }
        Serial.println();

        /*
         * Finally, check the received data and perform actions according to the received command
         */
        if (IrReceiver.decodedIRData.command == 0xB0) {
          Serial.println("Forward");
          Forward ();
          delay (1000);
          Stop ();  
          delay (5);// do something

        } else if (IrReceiver.decodedIRData.command == 0xB2) {
          Serial.println("Reverse");
          Reverse ();
          delay (1000);
          Stop ();  
          delay (5);// do something

        } else if (IrReceiver.decodedIRData.command == 0xB1) {
          Serial.println("Right");
          Right ();
          delay (1000);
          Stop ();
          delay (5);

        } else if (IrReceiver.decodedIRData.command == 0xB3) {
          Serial.println("Left");
          Left ();
          delay (1000);
          Stop ();
          delay (5);

        } else if (IrReceiver.decodedIRData.command == 0x85) {
          Serial.println("Stop");
          Stop ();
          delay (500);
        }
    }
}

And finally we used a Change State to make it move constantly until it receives a new instruction...

/*
 * SimpleReceiver.cpp
 *
 * Demonstrates receiving ONLY NEC protocol IR codes with IRremote
 * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
 *
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 ************************************************************************************
 * MIT License
 *
 * Copyright (c) 2020-2023 Armin Joachimsmeyer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************************
 */

/*
 * Specify which protocol(s) should be used for decoding.
 * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
 * This must be done before the #include <IRremote.hpp>
 */
//#define DECODE_DENON        // Includes Sharp
//#define DECODE_JVC
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC    // alias for DECODE_KASEIKYO
//#define DECODE_LG
//#define DECODE_NEC          // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
//#define DECODE_RC6

//#define DECODE_BOSEWAVE
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST

//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH         // special decoder for all protocols

//#define DECODE_BEO          // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!

//#define DEBUG               // Activate this for lots of lovely debug output from the decoders.

//#define RAW_BUFFER_LENGTH  180  // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.

#include <Arduino.h>

/*
 * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
 */
#include "PinDefinitionsAndMore.h"
#include <IRremote.hpp> // include the library

int sensorvalue = 0;

int motor1pin1 = 2;
int motor1pin2 = 3;

int motor2pin1 = 4;
int motor2pin2 = 5;

int Forward(){
              digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);
} 

int Stop(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, LOW);
}

int Reverse(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, HIGH);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, HIGH);
}

int Right(){
            digitalWrite(motor1pin1, HIGH);
            digitalWrite(motor1pin2, LOW);

            digitalWrite(motor2pin1, LOW);
            digitalWrite(motor2pin2, HIGH);
}

int Left(){
            digitalWrite(motor1pin1, LOW);
            digitalWrite(motor1pin2, HIGH);

            digitalWrite(motor2pin1, HIGH);
            digitalWrite(motor2pin2, LOW);  
}



void setup() {

  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);
    
    Serial.begin(115200);
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    printActiveIRProtocols(&Serial);
    Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
  
}

void loop() {
    /*
     * Check if received data is available and if yes, try to decode it.
     * Decoded result is in the IrReceiver.decodedIRData structure.
     *
     * E.g. command is in IrReceiver.decodedIRData.command
     * address is in command is in IrReceiver.decodedIRData.address
     * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
     */
    if (IrReceiver.decode()) {

        /*
         * Print a summary of received data
         */
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
            // We have an unknown protocol here, print extended info
            IrReceiver.printIRResultRawFormatted(&Serial, true);
            IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
        } else {
            IrReceiver.resume(); // Early enable receiving of the next IR frame
            IrReceiver.printIRResultShort(&Serial);
            IrReceiver.printIRSendUsage(&Serial);
        }
        Serial.println();
        /*
         * Finally, check the received data and perform actions according to the received command
         */
        if (IrReceiver.decodedIRData.command == 0xB0) {
          Serial.println("Forward");
          sensorvalue = 1;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB2) {
          Serial.println("Reverse");
          sensorvalue = 2;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB1) {
          Serial.println("Right");
          sensorvalue = 3;

        } else if (IrReceiver.decodedIRData.command == 0xB3) {
          Serial.println("Left");
          sensorvalue = 4;

        } else if (IrReceiver.decodedIRData.command == 0x85) {
          Serial.println("Stop");
          sensorvalue = 0;
        }
        
      if (sensorvalue == 0) {
        Stop ();
    
      } else if (sensorvalue == 1) {
        Forward ();
    
      } else if (sensorvalue == 2) {
        Reverse ();
    
      } else if (sensorvalue == 3) {
        Right ();
    
      } else if (sensorvalue == 4) {
        Left ();
        
      }
    }
}

We had to tinker with the PinDefinitionsAndMore.h to make pin-out match, but it's working well.

Finally, is there a better way to declare the functions at the beginning rather than int?

Thanks!

Thanks,

We didn't have a compiler warning or any crashes or unexpected behavior, but I'm glad to know the best practice way to define the functions.

Thanks again!

is this referring to the "int" function return type that should be replaced with void since the function do not return anything

void Forward () {

Thanks! I changed them over, and everything does what I expect it to do!

Updated code without the boilerplate on top:

#include <Arduino.h>

/*
 * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
 */
#include "PinDefinitionsAndMore.h"
#include <IRremote.hpp> // include the library

#include <Stepper.h>

const int stepsPerRevolution = 200; //Change this to match the stepper

int sensorvalue = 0;

int motor1pin1 = 2;
int motor1pin2 = 3;

int motor2pin1 = 4;
int motor2pin2 = 5;

Stepper myStepper(stepsPerRevolution, 7, 8, 9, 10);

String Forwardnote = "Forward";
String Reversenote = "Beeeep, Beeeep";
String Rightnote = "Right Turn";
String Leftnote = "Left Turn";
String Stopnote = "Stop";
String Raisenote = "Raising";
String Dropnote = "Lowering";

void Forward(){
              digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);
} 

void Stop(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, LOW);

              digitalWrite(7, LOW);
              digitalWrite(8, LOW);
              digitalWrite(9, LOW);
              digitalWrite(10, LOW);
}

void Reverse(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, HIGH);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, HIGH);
}

void Right(){
            digitalWrite(motor1pin1, HIGH);
            digitalWrite(motor1pin2, LOW);

            digitalWrite(motor2pin1, LOW);
            digitalWrite(motor2pin2, HIGH);
}

void Left(){
            digitalWrite(motor1pin1, LOW);
            digitalWrite(motor1pin2, HIGH);

            digitalWrite(motor2pin1, HIGH);
            digitalWrite(motor2pin2, LOW);  
}

void Raise(){
            Serial.println(Raisenote);
            myStepper.step(stepsPerRevolution);
            delay(500);
            Stop();
            Serial.println(Stopnote);
}

void Lower(){
            Serial.println(Dropnote);
            myStepper.step(-stepsPerRevolution);
            delay(500);
            Stop();
          Serial.println(Stopnote);
}


void setup() {

  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);

    Serial.begin(115200);
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    printActiveIRProtocols(&Serial);
    Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
  
}

void loop() {
    /*
     * Check if received data is available and if yes, try to decode it.
     * Decoded result is in the IrReceiver.decodedIRData structure.
     *
     * E.g. command is in IrReceiver.decodedIRData.command
     * address is in command is in IrReceiver.decodedIRData.address
     * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
     */
    if (IrReceiver.decode()) {

        /*
         * Print a summary of received data
         */
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
            // We have an unknown protocol here, print extended info
            IrReceiver.printIRResultRawFormatted(&Serial, true);
            IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
        } else {
            IrReceiver.resume(); // Early enable receiving of the next IR frame
            IrReceiver.printIRResultShort(&Serial);
            IrReceiver.printIRSendUsage(&Serial);
        }
        Serial.println();
        /*
         * Finally, check the received data and perform actions according to the received command
         */
        if (IrReceiver.decodedIRData.command == 0xB0) {
          sensorvalue = 1;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB2) {
          sensorvalue = 2;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB1) {         
          sensorvalue = 3;

        } else if (IrReceiver.decodedIRData.command == 0xB3) {          
          sensorvalue = 4;

        } else if (IrReceiver.decodedIRData.command == 0x85) {
          sensorvalue = 0;

        } else if (IrReceiver.decodedIRData.command == 0x86) {
          sensorvalue = 5;

        } else if (IrReceiver.decodedIRData.command == 0x87) {
          sensorvalue = 6;

        }
        
      if (sensorvalue == 0) {
        Stop ();
        Serial.println(Stopnote);
    
      } else if (sensorvalue == 1) {
        Forward ();
        Serial.println(Forwardnote);
    
      } else if (sensorvalue == 2) {
        Reverse ();
        Serial.println(Reversenote);
    
      } else if (sensorvalue == 3) {
        Right ();
        Serial.println(Rightnote);
    
      } else if (sensorvalue == 4) {
        Left ();
        Serial.println(Leftnote);
        
      } else if (sensorvalue == 5) {
        Serial.println(Raisenote);
        Raise ();
        
      } else if (sensorvalue == 6) {
        Serial.println(Dropnote);
        Lower();

      }
    }
}

For the latest in the saga...

We added a flag-pole and a stepper motor to raise and lower a flag. We were hoping to have it play a tune while the flag was lowering. It works great, except...

After the tune plays, the IR receiver stops interpreting the signals correctly. If anyone can help point out the downfall, please let me know. Here is the code:

/*
 * SimpleReceiver.cpp
 *
 * Demonstrates receiving ONLY NEC protocol IR codes with IRremote
 * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
 *
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 ************************************************************************************
 * MIT License
 *
 * Copyright (c) 2020-2023 Armin Joachimsmeyer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************************
 */

/*
 * Specify which protocol(s) should be used for decoding.
 * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
 * This must be done before the #include <IRremote.hpp>
 */
/*#define DECODE_DENON        // Includes Sharp
 * #define DECODE_JVC
 * #define DECODE_KASEIKYO
 * #define DECODE_PANASONIC    // alias for DECODE_KASEIKYO
 * #define DECODE_LG
 * #define DECODE_NEC          // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
 * #define DECODE_SAMSUNG
 * #define DECODE_SONY
 * #define DECODE_RC5
 * #define DECODE_RC6
 * #define DECODE_BOSEWAVE
 * #define DECODE_LEGO_PF
 * #define DECODE_MAGIQUEST
 * #define DECODE_WHYNTER
 * #define DECODE_FAST
 * #define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
 * #define DECODE_HASH         // special decoder for all protocols
 * #define DECODE_BEO          // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
 * #define DEBUG               // Activate this for lots of lovely debug output from the decoders.
 * #define RAW_BUFFER_LENGTH  180  // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
 */

#include <Arduino.h> //This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
#include "PinDefinitionsAndMore.h" //This includes Pin 11 as IR receive pin
#include <IRremote.hpp> // include the library
#include "Notes.h"
#include <Stepper.h>

const int stepsPerRevolution = 200; //Change this to match the stepper

int sensorvalue = 0; 

const int motor1pin1 = 2;
const int motor1pin2 = 3;
const int motor2pin1 = 4;
const int motor2pin2 = 5;

Stepper myStepper(stepsPerRevolution, 7, 8, 9, 10);

const int speakerPin = 12;
const int flagpole[] = {27,                                               // Array for Flag pole sound effect & song
  NOTE_G2, 10, NOTE_C3, 10, NOTE_E3, 10, NOTE_G3, 10, NOTE_C4, 10, NOTE_E4, 10, NOTE_G4, 3, NOTE_E4, 3, NOTE_GS2, 10, NOTE_C3, 10, 
  NOTE_DS3, 10, NOTE_GS3, 10, NOTE_C4, 10, NOTE_DS4, 10, NOTE_GS4, 3, NOTE_DS4, 3, NOTE_AS2, 10, NOTE_D3, 10, NOTE_F3, 10, 
  NOTE_AS3, 10, NOTE_D4, 10, NOTE_F4, 10, NOTE_AS4, 3, NOTE_AS4, 10, NOTE_AS4, 10, NOTE_AS4, 10, NOTE_C5, 2};

const int death[] = {17,                                                  // Array for Death sound effect & song
  NOTE_C4, 32, NOTE_CS4, 32, NOTE_D4, 16, NOTE_H, 4, NOTE_H, 2, NOTE_B3, 8, NOTE_F4, 8, NOTE_H, 8, NOTE_F4, 8, NOTE_F4, 6, 
  NOTE_E4, 6, NOTE_D4, 6, NOTE_C4, 8, NOTE_E3, 8, NOTE_H, 8, NOTE_E3, 8, NOTE_C3, 8};

const int gameover[] = {15,                                               // Array for Game over song
  NOTE_C4, 8, NOTE_H, 8, NOTE_H, 8, NOTE_G3, 8, NOTE_H, 4, NOTE_E3, 4, NOTE_A3, 6, NOTE_B3, 6, NOTE_A3, 6, NOTE_GS3, 6, NOTE_AS3, 6, 
  NOTE_GS3, 6, NOTE_G3, 8, NOTE_F3, 8, NOTE_G3, 4};

String Forwardnote = "Forward";
String Reversenote = "Beeeep, Beeeep";
String Rightnote = "Right Turn";
String Leftnote = "Left Turn";
String Stopnote = "Stop";
String Raisenote = "Raising";
String Dropnote = "Lowering";

void Forward(){
              digitalWrite(motor1pin1, HIGH);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, HIGH);
              digitalWrite(motor2pin2, LOW);
} 
void Stop(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, LOW);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, LOW);
}
void Reverse(){
              digitalWrite(motor1pin1, LOW);
              digitalWrite(motor1pin2, HIGH);

              digitalWrite(motor2pin1, LOW);
              digitalWrite(motor2pin2, HIGH);
}
void Right(){
            digitalWrite(motor1pin1, HIGH);
            digitalWrite(motor1pin2, LOW);

            digitalWrite(motor2pin1, LOW);
            digitalWrite(motor2pin2, HIGH);
}
void Left(){
            digitalWrite(motor1pin1, LOW);
            digitalWrite(motor1pin2, HIGH);

            digitalWrite(motor2pin1, HIGH);
            digitalWrite(motor2pin2, LOW);  
}
void Raise(){
            Serial.println("Raising");
            myStepper.step(stepsPerRevolution);
            delay(500);
            Stop();
}
void Lower(){
            Serial.println("Lowering");
            myStepper.step(-stepsPerRevolution);
            delay(500);
            Stop();
}

void FlagSong(){
            for (int thisNote = 1; thisNote < (flagpole[0] * 2 + 1); thisNote = thisNote + 2) { // Run through the notes one at a time
            tone(speakerPin, flagpole[thisNote], (1000/flagpole[thisNote + 1]));// Play the single note
            delay((1000/flagpole[thisNote + 1]) * 1.30);                        // Delay for the specified time
            noTone(speakerPin);                                                 // Silence the note that was playing
            } 
            Serial.println("Done");
}

void setup() {

  pinMode(motor1pin1, OUTPUT);
  pinMode(motor1pin2, OUTPUT);
  pinMode(motor2pin1, OUTPUT);
  pinMode(motor2pin2, OUTPUT);

  pinMode(speakerPin, OUTPUT);

//Stepper motor pinouts initialized as output in Stepper.h

    Serial.begin(115200);
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    printActiveIRProtocols(&Serial);
    Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
  
}

void loop() {
    /*
     * Check if received data is available and if yes, try to decode it.
     * Decoded result is in the IrReceiver.decodedIRData structure.
     *
     * E.g. command is in IrReceiver.decodedIRData.command
     * address is in command is in IrReceiver.decodedIRData.address
     * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
     */
    if (IrReceiver.decode()) {

        /*
         * Print a summary of received data
         */
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
            // We have an unknown protocol here, print extended info
            IrReceiver.printIRResultRawFormatted(&Serial, true);
            IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()

        } else {
            IrReceiver.resume(); // Early enable receiving of the next IR frame
            IrReceiver.printIRResultShort(&Serial);
            IrReceiver.printIRSendUsage(&Serial);
        }
        Serial.println();
        /*
         * Finally, check the received data and perform actions according to the received command
         */
        if (IrReceiver.decodedIRData.command == 0xB0) {
          Serial.println(Forwardnote);
          sensorvalue = 1;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB2) {
          Serial.println(Reversenote);
          sensorvalue = 2;// do something

        } else if (IrReceiver.decodedIRData.command == 0xB1) {         
          Serial.println(Rightnote);
          sensorvalue = 3;

        } else if (IrReceiver.decodedIRData.command == 0xB3) {          
          Serial.println(Leftnote);
          sensorvalue = 4;

        } else if (IrReceiver.decodedIRData.command == 0x85) {
          Serial.println(Stopnote);
          sensorvalue = 0;

        } else if (IrReceiver.decodedIRData.command == 0x86) {
          Serial.println(Raisenote);
          Raise();

        } else if (IrReceiver.decodedIRData.command == 0x87) {
          Serial.println(Dropnote);
          Lower();
          FlagSong();

        } else if (IrReceiver.decodedIRData.command == 0x98) {
          Serial.println("dead");

        } else if (IrReceiver.decodedIRData.command == 0x99) {
          Serial.println("game over");

        }
      
                
      if (sensorvalue == 0) {
        Stop ();
    
      } else if (sensorvalue == 1) {
        Forward ();
    
      } else if (sensorvalue == 2) {
        Reverse ();
    
      } else if (sensorvalue == 3) {
        Right ();
    
      } else if (sensorvalue == 4) {
        Left ();
        
      }
    }
} //void loop close
/*
Why is this unable to read IR signals after the flagsong?
*/

And here is part of the Serial Printout (after the "Lowering" the "Stop" command was sent, but wasn't decoded correctly as it had been earlier):

Protocol=NEC Address=0x5583 Command=0x85 Raw-Data=0x7A855583 32 bits LSB first
Send with: IrSender.sendNEC(0x5583, 0x85, );

Stop
Protocol=NEC Address=0x5583 Command=0x87 Raw-Data=0x78875583 32 bits LSB first
Send with: IrSender.sendNEC(0x5583, 0x87, );

Lowering
Lowering
Done
Received noise or an unknown (or not yet enabled) protocol
rawData[30]:
-1196250

  • 450,- 200
  • 50,- 50 + 50,- 50 + 50,- 200 + 100,- 50
  • 50,- 50 + 50,- 200 + 50,- 50 + 100,- 50
  • 50,- 300 + 200,- 300 + 100,- 50 + 50,- 50
  • 50,- 200 + 50
    Sum: 3250

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