Help me with code

Hello, I have a problem with the code, when I try to run it it does not access the command, for example when I press a it is supposed to print something and it does not print it

#include <Arduino.h>
#include <Wire.h>
#include <EEPROM.h>
#include "timer.h"
#include "lsm.h"
#include "mot.h"

//User configuration section:
//Please uncomment only one of each of the following MotorTypes, SensorTypes and SerialPort types:
//const int MotorType = PWMDIR;     //Please uncomment this line for the LMD18200T DC motor driver.
const int MotorType = FWDREV;       //Please uncomment this line for the L298N DC motor driver.
//const int MotorType = ACMOTR;     //Please uncomment this line for the triac AC motor driver.
//const int SensorType = LSM303D;   //Please uncomment this line to use the LSM303D sensor.
const int SensorType = LSM303DLHC;  //Please uncomment this line to use the LSM303DLHC sensor.
#define SerialPort Serial           //Please uncomment this line to use the USB port.
//#define SerialPort Serial1        //Please uncomment this line to use the TTL port.
#define WINDUP_LIMIT 450            //Sets the total number of degrees azimuth rotation in any direction before resetting to zero
//Motor pins - Don't change
const int azFwdPin = 5;
const int azRevPin = 6;
const int elFwdPin = 9;
const int elRevPin = 10;
//Speaker pins
const int gndPin = 14;    //Makes a convenient ground pin adjacent to the speaker pin
const int spkPin = 16;    //Attach a piezo buzzer to this pin. It beeps when new calibration data arrives.
//Motor drive gains. These set the amount of motor drive close to the set point
const int azGain = 25;   //Azimuth motor gain
const int elGain = 25;   //Elevation motor gain
//Filter constants
const float azAlpha = 0.5; //Alpha value for AZ motor filter: Decrease to slow response time and reduce motor dither.
const float elAlpha = 0.5; //Alpha value for EL motor filter: Decrease to slow response time and reduce motor dither.
const float lsmAlpha = 0.05; //Alpha value for sensor filter: Decrease to slow response time and ease calibration process.

enum Modes {tracking, monitoring, demonstrating, calibrating, debugging, pausing};    //Rotator controller modes

//Global variables
float az;               //Antenna azimuth
float el;               //Antenna elevation
String line;            //Command line
float azSet;            //Antenna azimuth set point
float elSet;            //Antenna elevation set point
float azLast;           //Last antenna azimuth reading
float elLast;           //Last antenna element reading
float azWindup;         //Antenna windup angle from startup azimuth position
float azOffset;         //Antenna azimuth offset for whole revolutions
bool windup;            //Antenna windup condition
float azSpeed;          //Antenna azimuth motor speed
float elSpeed;          //Antenna elevation motor speed
float azError;          //Antenna azimuth error
float elError;          //Antenna elevation error
float azInc;            //AZ increment for demo mode
float elInc;            //EL increment for demo mode
Modes mode;             //Rotator mode


//Motor driver object: Mot xxMot(Driver-Type, Filter-Alpha, Gain, Fwd-Pin, Rev/Dir-Pin)
Mot azMot(MotorType, azAlpha, azGain, azFwdPin, azRevPin); //AZ motor driver object
Mot elMot(MotorType, elAlpha, elGain, elFwdPin, elRevPin); //EL motor driver object

//LSM sensor object: Lsm lsm(Sensor-Type, Filter-Alpha)
Lsm lsm(SensorType,lsmAlpha);

//Non-blocking Timer object
Timer t1(100);

void reset(bool getCal) {
  //Reset the rotator, initialize its variables and optionally get the stored calibration
  azSet = 0.0;
  elSet = 0.0;
  line = "";
  azLast = 0.0;
  elLast = 0.0;
  azWindup = 0.0;
  azOffset = 0.0;
  azSpeed = 0.0;
  elSpeed = 0.0;
  mode = tracking;
  windup = false;
  if (getCal) restore();
  azError = 0.0;
  elError = 0.0;
  azInc = 0.05;
  elInc = 0.05;
  lsm.calStart(); //Reset the axis calibration objects

float diffAngle(float a, float b) {
  //Calculate the acute angle between two angles in -180..180 degree format
  float diff = a - b;
  if (diff < -180) diff += 360;
  if (diff > 180) diff -= 360;
  return diff;

void save() {
  //Save the calibration data to EEPROM

void restore() {
  //Restore the calibration data from EEPROM

void printDebug(void) {
  //Print raw sensor data
  SerialPort.print(; SerialPort.print(",");
  SerialPort.print(; SerialPort.print(",");
  SerialPort.print(; SerialPort.print(",");
  SerialPort.print(lsm.gx); SerialPort.print(",");
  SerialPort.print(; SerialPort.print(",");

void printCal(void) {
  //Print the calibration data
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.print(, 1); SerialPort.print(",");
  SerialPort.println(, 1);

void printMon(float az, float el, float azSet, float elSet, float azWindup, float azError, float elError) {
  //Print the monitor data
  SerialPort.print(az, 0); SerialPort.print(",");
  SerialPort.print(el, 0); SerialPort.print(",");
  SerialPort.print(azSet, 0); SerialPort.print(",");
  SerialPort.print(elSet, 0); SerialPort.print(",");
  SerialPort.print(azWindup, 0); SerialPort.print(",");
  SerialPort.print(windup); SerialPort.print(",");
  SerialPort.print(azError, 0); SerialPort.print(",");
  SerialPort.println(elError, 0);

void printAzEl() {
  //Print the rotator feedback data in Easycomm II format
  SerialPort.print((az < 0) ? (az + 360) : az, 1);
  SerialPort.print(" EL");
  SerialPort.print(el, 1);

void calibrate() {
  //Process raw accelerometer and magnetometer samples
  bool changed = lsm.calibrate();
  //Print any changes and beep the speaker to facilitate manual calibration
  if (changed) {
    digitalWrite(spkPin, HIGH);     //Sound the piezo buzzer
    printCal();                     //Print the calibration data
  } else {
    digitalWrite(spkPin, LOW);      //Silence the piezo buzzer

void getWindup(bool *windup,  float *azWindup, float *azOffset, float *azLast, float *elLast, float az, float elSet) {
  //Get the accumulated windup angle from the home position (startup or last reset position) and set the windup state if greater than the limit.
  //Get the raw difference angle between the current and last azimuth reading from the sensor
  float azDiff = az - *azLast;

  //Detect crossing South: azDiff jumps 360 for a clockwise crossing or -360 for an anticlockwise crossing
  //Increment the azimuth offset accordingly
  if (azDiff < -180) *azOffset += 360;
  if (azDiff > 180) *azOffset -= 360;

  //Save the current azimuth reading for the next iteration
  *azLast = az;

  //Compute the azimuth wind-up angle, i.e. the absolute number of degrees from the home position
  *azWindup = az + *azOffset;

  //Detect a windup condition where the antenna has rotated more than 450 degrees from home
  if (abs(*azWindup) > WINDUP_LIMIT) *windup = true;    //Set the windup condition - it is reset later when the antenna nears home

  //Perform the anti-windup procedure at the end of each pass - This is overkill unless you absolutely don't want anti-windup during a pass
  //  if (elSet <= 0)
  //    if (elLast > 0)
  //      if (mode == tracking) {
  //        *windup = true;
  //      }

  //Save the current elevation reading for the next iteration
  *elLast = elSet;

void getAzElDemo(float *azSet, float *elSet, float *azInc, float *elInc) {
  //Autoincrement the azimuth and elevation to demo the rotator operation
  if (*azSet > 180.0) *azInc = -*azInc;
  if (*azSet < -180.0) *azInc = -*azInc;
  if (*elSet > 90.0) *elInc = -*elInc;
  if (*elSet < 0.0) *elInc = -*elInc;
  *azSet += *azInc;
  *elSet += *elInc;
  SerialPort.print(*azSet, 0); SerialPort.print(",");
  SerialPort.println(*elSet, 0);

void getAzElError(float *azError, float *elError, bool *windup, float *azSet, float elSet, float az, float el) {
  //Compute the azimuth and elevation antenna pointing errors, i.e. angular offsets from set positions
  //Compute the azimuth antenna pointing error: Normally via the shortest path; opposite if windup detected.
  if (*windup) {                               //Check for a windup condition
    //To unwind the antenna set an azError in the appropriate direction to home
    *azError = constrain(azWindup, -180, 180); //Limit the maximum azimuth error to -180..180 degrees
    //Cancel the windup condition when the antenna is within 180 degrees of home (Actually 175 degrees to avoid rotation direction ambiguity)
    //Set a zero home position by default, but return azumith control to the computer if still connected
    if (abs(*azError) < 175) *windup = false; //Cancel windup and permit computer control
  else {
    //Compute the normal azimuth antenna pointing error when there is no windup condition
    *azError = diffAngle(az, *azSet);

  //Compute the elevation antenna pointing error
  *elError = diffAngle(el, elSet);

void processPosition() {
  //Perform the main operation of positioning the rotator under different modes
  //Read the accelerometer and magnetometer
  switch (mode) {
    case debugging:
      printDebug(); //Print the raw sensor data for debug purposes
    case calibrating:
      calibrate();  //Process calibration data
    case pausing:
      azMot.halt(); //Stop the AZ motor
      elMot.halt(); //Stop the EL motor
      lsm.getAzEl();  //Get the azimuth and elevation of the antenna                                                              //Get the antenna AZ and EL
      az =;
      el = lsm.el;
      getWindup(&windup, &azWindup, &azOffset, &azLast, &elLast, az, elSet);      //Get the AZ windup angle and windup state
      if (mode == demonstrating) getAzElDemo(&azSet, &elSet, &azInc, &elInc);     //Set the AZ and EL automatically if in demo mode
      getAzElError(&azError, &elError, &windup, &azSet, elSet, az, el);           //Get the antenna pointing error
      if (mode == monitoring) printMon(az, el, azSet, elSet, azWindup, azError, elError); //Print the data if in monitor mode

void processMotors() {
  //Drive the motors to reduce the azimuth and elevation error to zero;;

void processUserCommands(String line) {
  //Process user commands
  //User command type 1: r, b, m, c, a, d, s, d, h, p or e<decl> followed by a carriage return
  //User command type 2: <az> <el> followed by a carriage return
  String param;                                           //Parameter value
  int firstSpace;                                         //Position of the first space in the command line
  char command = line.charAt(0);                          //Get the first character
  switch (command) {                                      //Process type 1 user commands
    case 'r':                                             //Reset command
      SerialPort.println("Reset in progress");
      reset(true);  //Reset the rotator and load calibration from EEPROM
      SerialPort.println("Reset complete");
    case 'b':                                             //Debug command
      SerialPort.println("Debugging in progress: Press 'a' to abort");
      mode = debugging;
    case 'm':                                             //Monitor command
      SerialPort.println("Monitoring in progress: Press 'a' to abort");
      mode = monitoring;
    case 'c':                                             //Calibrate command
      SerialPort.println("Calibration in progress: Press 'a' to abort or 's' to save");
      reset(false); //Reset the rotator, but don't load calibration from EEPROM
      mode = calibrating;
    case 'a':                                             //Abort command
      mode = tracking;
      SerialPort.println("Function aborted");
    case 'e':                                             //Magnetic declination command
      param = line.substring(1);                          //Get the second parameter = param.toFloat();
    case 's':                                             //Save command
      SerialPort.println("Calibration saved");
    case 'd':                                             //Demo command
      SerialPort.println("Demo in progress: Press 'a' to abort");
      mode = demonstrating;
    case 'h':                                             //Help command
      SerialPort.println("az el -(0..360 0..90)");
      SerialPort.println("r -Reset");
      SerialPort.println("eNN.N -MagDecl");
      SerialPort.println("c -Calibrate");
      SerialPort.println("s -Save");
      SerialPort.println("a -Abort");
      SerialPort.println("d -Demo");
      SerialPort.println("b -Debug");
      SerialPort.println("m -Monitor");
      SerialPort.println("p -Pause");
    case 'p':                                             //Pause command
      if (mode == pausing) {
        mode = tracking;
      } else {
        mode = pausing;
    default:                                              //Process type 2 user commands
      firstSpace = line.indexOf(' ');                     //Get the index of the first space
      param = line.substring(0, firstSpace);              //Get the first parameter
      azSet = param.toFloat();                            //Get the azSet value
      param = line.substring(firstSpace + 1);             //Get the second parameter
      elSet = param.toFloat();                            //Get the elSet value

void processEasycommCommands(String line) {
  //Process Easycomm II rotator commands
  //Easycomm II position command: AZnn.n ELnn.n UP000 XXX DN000 XXX\n
  //Easycomm II query command: AZ EL \n
  String param;                                           //Parameter value
  int firstSpace;                                         //Position of the first space in the command line
  int secondSpace;                                        //Position of the second space in the command line
  if (line.startsWith("AZ EL")) {                         //Query command received
    printAzEl();                                          //Send the current Azimuth and Elevation
  } else {
    if (line.startsWith("AZ")) {                          //Position command received: Parse the line.
      firstSpace = line.indexOf(' ');                     //Get the position of the first space
      secondSpace = line.indexOf(' ', firstSpace + 1);    //Get the position of the second space
      param = line.substring(2, firstSpace);              //Get the first parameter
      azSet = param.toFloat();                            //Set the azSet value
      if (azSet > 180) azSet = azSet - 360;               //Convert 0..360 to -180..180 degrees format
      param = line.substring(firstSpace + 3, secondSpace);//Get the second parameter
      elSet = param.toFloat();                            //Set the elSet value

void processCommands(void) {
  //Process incoming data from the control computer
  //User commands are entered by the user and are terminated with a carriage return
  //Easycomm commands are generated by a tracking program and are terminated with a line feed
  while (SerialPort.available() > 0) {
    char ch =;                                //Read a single character from the serial buffer
    switch (ch) {
      case 13:                                                  //Carriage return received
        processUserCommands(line);                              //Process user commands
        line = "";                                              //Command processed: Clear the command line
      case 10:                                                  //Line feed received
        processEasycommCommands(line);                          //Process Easycomm commands
        line = "";                                              //Command processed: Clear the command line
      default:                                                  //Any other character received
        line += ch;                                             //Add this character to the command line

void setup() {
  //Initialize the system
  //Set speaker pins to outputs
  pinMode(spkPin, OUTPUT);
  pinMode(gndPin, OUTPUT);
  digitalWrite(gndPin, LOW);
  //Reset the rotator and load configuration from EEPROM
  //Initialize the serial port
  //Initialize the sensor

void loop() {
  //Repeat continuously
  processCommands();                                              //Process commands from the control computer
  t1.execute(&processPosition);                                   //Process position only periodically
  processMotors();                                                //Process motor drive
} (16.3 KB)
The code with the zip file

That's a huuuge sketch to have written without testing each part as you developed it. Wise strategy is to test as you go.

But as far as I can see, you should be typing an 'a' not an 'A'.

//User command type 1: r, b, m, c, **a**, d, s, d, h, p or e<decl> followed by a carriage return

1 Like

Are you entering A or a ? Your code tests for the latter

What do you see when you print the line String in the processUserCommands() function ?

when I press a not a it is supposed to print something

You appear to be the same person, is this correct?


Sorry but you can't have 2 accounts, which one do you want to use?


i press a

I have suspended @netaniels.
Please do not create any more accounts, if you do then all of them will be suspended.
Thank you.

¿Que? I assume that's a typo.

Only really sensible way to test code is to test as you go- ensure you have that part (for example) working in isolation before you cloud the issue by adding tons more code.

On the other hand if it's not your own code, ask the author.

This part works when I copy it and put it in the part of the void loop

What do you have for line ending in the serial monitor?

Nobody can guess what "this part" means.

But if it's the part that reads the input and prints stuff when you type an 'a' that's good progress towards trouble-shooting. Now add other parts of the code and see when it falls over.

My problem is that it does not access part of processCommands
When I tried to copy only the part of processUserCommands into the void loop it did work
And the part I meant was processUserCommands

What do you mean?

There's a dropdown in the serial monitor of the IDE that lets you select what characters, if any, are sent after whatever you type when you press enter. How it's set can make a difference depending on your code.

I don't have all your libraries, so I commented them out and everything related that started throwing complier errors. Sent it to an uno and tested. Sending 'a' worked with 'both NL and CR', didn't with 'No line ending'.

If I understand correctly what you mean it's char

Great fault finding approach by wildbill, but OP does say this (my emphasis):