body:
I am getting multiple messages from a GPS device at different frequencies. After getting strings I have to save this data on the SD card. It works well when we have the same frequencies messages but if the frequencies are not same the saved data gets some blank spaces.
I am using the split strings method.

```c++
    CR1A = String1.indexOf(13);  //finds location of first
    String1A = String1.substring(0, CR1A + 2 );   //captures first data String
    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,
    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String
    CR1C = String1.indexOf(13, CR1B + 2 );
    String1C = String1.substring(CR1B , CR1C + 2 );
    CR1D = String1.indexOf(13, CR1C + 2 );
    String1D = String1.substring(CR1C , CR1D + 2 );
    CR1E = String1.indexOf(13, CR1D + 2 );
    String1E = String1.substring(CR1D , CR1E + 2 );
    CR1F = String1.indexOf(13, CR1E + 2 );
    String1F = String1.substring(CR1E , CR1F + 2 );

    strID = (String1A.substring(0, 2));
    if (strID == "$G") {
      File dataFile = SD.open("GPS1.txt", FILE_WRITE);
      // if the file is available, write to it:

      strID = (String1A.substring(0, 5));
      if (strID == "$GPGG") {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.print(String1A);
        String1A = "";
      }

      strID = (String1D.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1B);
        String1B = "";
      }
      strID = (String1C.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1C);
        String1C = "";
      }
      strID = (String1D.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1D);
        String1D = "";
      }
      strID = (String1E.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1E);
        String1E = "";
      }
      strID = (String1F.substring(4, 6));
      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
        dataFile.print(String1F);
        String1F = "";
      }
      dataFile.close();
    }
```

---
EDIT:

This is the code now I am using. I have turned off all the commands which extract strings from my available data received at the serial port. I am just using an interrupt timer for it.. and it is working perfectly. But I didn't like this simple method and I don't know it's a good way to get strings like this or not as I am not a good programmer.

```
#include <TimerOne.h>
#define RxTimeOut 5

/*
  ** MEGA MINI **
  ** MOSI - pin 51
  ** MISO - pin 50
  ** CLK - pin 52
  ** CS - pin 53 (for MKRZero SD: SDCARD_SS_PIN)
  ** SDA - pin 20
  ** SCL - pin 21
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include "math.h"
#include <SPI.h>
#include <SD.h>
#include "RTClib.h"
#define DS1307_CTRL_ID 0x68
unsigned long int ticks = 0;
RTC_DS1307 rtc;
bool flag = false;
String GPSmessage = "";
const int chipSelect = 53;
String dataString = "";
//String dataString1 = "";
//String dataString2 = "";
//String dataString3 = "";
bool stringComplete = false;
bool string1Complete = false;
bool string2Complete = false;
bool string3Complete = false;
String strID = "";

unsigned long msec;
const long interval = 500;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

unsigned long CurrentBaudRate = 9600;

unsigned long x = 0;

int Up = 3;
int Dn = 4;
int Mnu = 5;

String String1;
String inputString1 = "";         // a String to hold incoming data
boolean NewDataFlag1 = 0;
unsigned int Serial1TimeOut = 0;

String String2;
String inputString2 = "";         // a String to hold incoming data
boolean NewDataFlag2 = 0;
unsigned int Serial2TimeOut = 0;

String String3;
String inputString3 = "";         // a String to hold incoming data
boolean NewDataFlag3 = 0;
unsigned int Serial3TimeOut = 0;

void timerIsr()
{
  serial1Event();
  serial2Event();
  serial3Event();

  if (Serial1TimeOut > 0)Serial1TimeOut--;
  if (Serial1TimeOut == 0 && NewDataFlag1 == 1)
  {
    String1 = inputString1;
    inputString1 = "";
    NewDataFlag1 = 0;
  }

  if (Serial2TimeOut > 0)Serial2TimeOut--;
  if (Serial2TimeOut == 0 && NewDataFlag2 == 1)
  {
    String2 = inputString2;
    inputString2 = "";
    NewDataFlag2 = 0;
  }

  if (Serial3TimeOut > 0)Serial3TimeOut--;
  if (Serial3TimeOut == 0 && NewDataFlag3 == 1)
  {
    String3 = inputString3;
    inputString3 = "";
    NewDataFlag3 = 0;
  }

}

void setup() {

  Timer1.initialize(5000); // Timer event time
  Timer1.attachInterrupt( timerIsr );

  Serial.println("Sonay di nathli");

  //========================================= SD Card =======================================================//
  //  Serial.println("Initializing SD card...");

  // see if the card is not present:
  if (!SD.begin(chipSelect)) {
    //    Serial.println("Card failed, or not present");
    //     don't do anything more:
    return;
  }
  //  Serial.println("SD card Ready");

  //====================================================== RTC =============================================//
  if (!rtc.begin())
  {
    //    Serial.println("Couldn't find RTC");
    Serial.flush();
    abort();
  }

  if (!rtc.isrunning()) {
    //    Serial.println("RTC is NOT running, let's set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  //================================================ OLED Baudrate selection ====================================================//
  pinMode(Up, INPUT_PULLUP);
  pinMode(Dn, INPUT_PULLUP);
  pinMode(Mnu, INPUT_PULLUP);

  unsigned char bdindx = EEPROM.read(0);
  if (bdindx > 3) bdindx = 0;
  if (bdindx == 0) CurrentBaudRate = 4800;
  if (bdindx == 1) CurrentBaudRate = 9600;
  if (bdindx == 2) CurrentBaudRate = 19200;
  if (bdindx == 3) CurrentBaudRate = 115200;
  delay (500);

  while (!Serial) { }// wait for serial port to connect
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(CurrentBaudRate);
  Serial1.begin(CurrentBaudRate);
  Serial2.begin(CurrentBaudRate);
  Serial3.begin(CurrentBaudRate);
  Serial.println(CurrentBaudRate);
  delay (1000);

  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.clearDisplay();
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.display();

}

String String1A, String1B, String1C, String1D, String1E, String1F;
String String2A, String2B, String2C, String2D, String2E, String2F;
String String3A, String3B, String3C, String3D, String3E, String3F;
int CR1A, CR1B, CR1C, CR1D, CR1E, CR1F;
int CR2A, CR2B, CR2C, CR2D, CR2E, CR2F;
int CR3A, CR3B, CR3C, CR3D, CR3E, CR3F;

// ============================================ Showing baud rate on screen (position) ===========================================//

void DrawBaudRate(unsigned long BdRt)
{
  unsigned char Xoffset = 0;
  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
  if (BdRt >= 100000 ) Xoffset = 25;
  //  display.drawRect(0,0,128,64,SSD1306_WHITE);
  //  display.setTextSize(2);
  //  display.setCursor(15,10);
  //  display.println("Baudrate");
  //  display.setTextSize(2);
  //  display.setCursor(15,10);
  //  display.println(tm);
  //  display.setCursor(Xoffset,37);// 6 digit
  //  display.println(BdRt);
  //  display.display();
  //  delay(10);
}

// ================================================== Selection of Baud Rate ========================================================//
unsigned long SelectBaudRate(unsigned long BdRt)
{
  unsigned char BdRtIndx = 0;
  unsigned int FlashCnt = 0;

  if (BdRt == 4800) BdRtIndx = 0;
  if (BdRt == 9600) BdRtIndx = 1;
  if (BdRt == 19200) BdRtIndx = 2;
  if (BdRt == 115200) BdRtIndx = 3;

  unsigned char Xoffset = 0;
  if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
  if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
  if (BdRt >= 100000 ) Xoffset = 25;
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(15, 10); display.println("Select Baudrate");
  display.setCursor(15, 20); display.println("by Up/Dn Buttons");
  display.setTextSize(2);
  display.setCursor(Xoffset, 37); // 6 digit
  display.println(BdRt);
  display.display();
  delay(10);

  while (digitalRead(Mnu) == 0) delay(10);
  delay(100);

  while (digitalRead(Mnu) == 1)
  {
    delay(10);
    FlashCnt++;

    if (digitalRead(Up) == 0)
    {
      if (BdRtIndx < 3) BdRtIndx++;
    }

    if (digitalRead(Dn) == 0)
    {
      if (BdRtIndx > 0) BdRtIndx--;
    }

    if (BdRtIndx == 0) BdRt = 4800;
    if (BdRtIndx == 1) BdRt = 9600;
    if (BdRtIndx == 2) BdRt = 19200;
    if (BdRtIndx == 3) BdRt = 115200;

    if (BdRt >= 0 && BdRt < 10000) Xoffset = 37;
    if (BdRt >= 10000 && BdRt < 100000) Xoffset = 30;
    if (BdRt >= 100000 ) Xoffset = 25;
    display.clearDisplay();
    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
    display.setTextSize(1);
    display.setCursor(15, 10); display.println("Select Baudrate");
    display.setCursor(15, 20); display.println("by Up/Dn Buttons");
    display.setTextSize(2);
    display.setCursor(Xoffset, 37); // 6 digit
    if (FlashCnt > 1) display.println(BdRt);
    if (FlashCnt > 2) FlashCnt = 0;
    display.display();
    delay(250);

    //while(digitalRead(Up)==0 || digitalRead(Dn)==0) delay(10);
  }
  while (digitalRead(Mnu) == 0) delay(10);

  display.clearDisplay();
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  display.setTextSize(2);
  display.setCursor(20, 10); display.println("Saving");
  display.setCursor(20, 35); display.println("Changes");
  display.display();
  delay(2000);

  EEPROM.write(0, BdRtIndx);

  return (BdRt);

}

//=================================================== OLED showing time ===============================================//
char Time[]     = "  :  :  ";
byte i, second, minute, hour;

void DS3231_display() {
  // Convert BCD to decimal
  second = (second >> 4) * 10 + (second & 0x0F);
  minute = (minute >> 4) * 10 + (minute & 0x0F);
  hour   = (hour >> 4)   * 10 + (hour & 0x0F);
  // End conversion

  Time[7]     = second % 10 + 48;
  Time[6]     = second / 10 + 48;
  Time[4]     = minute % 10 + 48;
  Time[3]     = minute / 10 + 48;
  Time[1]     = hour   % 10 + 48;
  Time[0]     = hour   / 10 + 48;
  display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  draw_text(16, 25, Time, 2);                         // Display the time
}

void blink_parameter() {
  byte j = 1;
  while (j < 10 && digitalRead(Up) && digitalRead(Dn)) {
    j++;
    delay(25);
  }
}

byte edit(byte x_pos, byte y_pos, byte parameter) {
  char text[3];
  sprintf(text, "u", parameter);
  while (!digitalRead(Up));                     // Wait until button B1 released
  while (true) {
    while (!digitalRead(Dn)) {                  // If button B2 is pressed
      display.clearDisplay();
      parameter++;
      if (i == 0 && parameter > 23)                  // If hours > 23 ==> hours = 0
        parameter = 0;
      if (i == 1 && parameter > 59)                  // If minutes > 59 ==> minutes = 0
        parameter = 0;
      sprintf(text, "u", parameter);
      draw_text(x_pos, y_pos, text, 2);
      delay(200);                                    // Wait 200ms
    }
    display.drawRect(0, 0, 128, 64, SSD1306_WHITE);
    draw_text(x_pos, y_pos, "  ", 2);
    blink_parameter();
    draw_text(x_pos, y_pos, text, 2);
    blink_parameter();
    if (!digitalRead(Up)) {                     // If button B1 is pressed
      i++;                                           // Increament 'i' for the next parameter
      //      display.clearDisplay();

      return parameter;                              // Return parameter value and exit
    }
  }
}

void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

//---------------------------------------------
void loop() {

  // ========================================= Editing time and displaying on OLED ============================================//
  if (!digitalRead(Up)) {                       // If button B1 is pressed
    i = 0;
    while (!digitalRead(Up));                   // Wait for button B1 release

    hour   = edit(16, 25, hour);                     // Edit hours
    minute = edit(52, 25, minute);                   // Edit minutes

    // Convert decimal to BCD
    minute = ((minute / 10) << 4) + (minute % 10);
    hour = ((hour / 10) << 4) + (hour % 10);
    // End conversion

    // Write data to DS3231 RTC
    Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address
    Wire.write(0);                              // Send register address
    Wire.write(0);                              // Reset sesonds and start oscillator
    Wire.write(minute);                         // Write minute
    Wire.write(hour);                           // Write hour
    Wire.endTransmission();                     // Stop transmission and release the I2C bus
    delay(200);                                 // Wait 200ms
  }

  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0);                                // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading
  second = Wire.read();                         // Read seconds from register 0
  minute = Wire.read();                         // Read minutes from register 1
  hour   = Wire.read();                         // Read hour from register 2
  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0x11);                             // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 2);                    // Request 2 bytes from DS3231 and release I2C bus at end of reading
  DS3231_display();                             // Diaplay time & calendar

  delay(50);                                    // Wait 50ms

  { display.clearDisplay();
    if (digitalRead(Mnu) == 0) CurrentBaudRate = SelectBaudRate(CurrentBaudRate);
    //  DrawBaudRate(CurrentBaudRate);
    delay(10);

    x++;
    if (x > 123456) x = 0;
  }

  // ======================================= Reading Date and Time from RTC =============================================//
  DateTime now = rtc.now();
  char dt[16];
  char tm[16];
  char buffer [16];
  uint8_t thisSec, thisMin, thisHour;
  thisSec = now.second();
  thisMin = now.minute();
  thisHour = now.hour();
  sprintf(dt, "d-d-d", now.year(), now.month(), now.day());
  sprintf(tm, "ddd", now.hour(), now.minute(), now.second());
  sprintf (buffer, "d:d:d", thisHour, thisMin, thisSec);
  msec = millis() % 1000; //TO USE LAST 3 DIGITS OF MILLIS OF ARDUINO

  //SERIAL_PORT_1

//  if (string1Complete)
  { Serial.print (String1);
//    CR1A = String1.indexOf(13);  //finds location of first
//    String1A = String1.substring(0, CR1A + 2 );   //captures first data String
//    CR1B = String1.indexOf(13, CR1A + 2 ); //finds location of second ,
//    String1B = String1.substring(CR1A , CR1B + 2 ); //captures second data String
//    CR1C = String1.indexOf(13, CR1B + 2 );
//    String1C = String1.substring(CR1B , CR1C + 2 );
//    CR1D = String1.indexOf(13, CR1C + 2 );
//    String1D = String1.substring(CR1C , CR1D + 2 );
//    CR1E = String1.indexOf(13, CR1D + 2 );
//    String1E = String1.substring(CR1D , CR1E + 2 );
//    CR1F = String1.indexOf(13, CR1E + 2 );
//    String1F = String1.substring(CR1E , CR1F + 2 );
//
//    strID = (String1A.substring(0, 5));
//    if (strID == "$GPGG") {
//      Serial.println(String1);
//    }
//    strID = (String1B.substring(0, 5));
//    if (strID == "$GPVT") {
//      Serial.println(String1B);
//    }
//    strID = (String1C.substring(0, 5));
//    if (strID == "$GPZD") {
//      Serial.println(String1C);
//    }
//    strID = (String1D.substring(0, 5));
//    if (strID == "$GPGL") {
//      Serial.println(String1D);
//    }
//    strID = (String1E.substring(0, 5));
//    if (strID == "$GPGN") {
//      Serial.println(String1E);
//    }
//    strID = (String1F.substring(0, 5));
//    if (strID == "$GPGR") {
//      Serial.println(String1F);
//    }
//    strID = (String1.substring(0, 2));
//    if (strID == "$") {
      File dataFile = SD.open("GPS1.txt", FILE_WRITE);
      // if the file is available, write to it:

      strID = (String1A.substring(0, 5));
      if (strID == "$GPGG") {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.print(String1);
        Serial.print (String1);
        String1 = "";
        Serial.print (String1);
        dataFile.close();
      }
//    }
//      strID = (String1D.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1B);
//        String1B = "";
//      }
//      strID = (String1C.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1C);
//        String1C = "";
//      }
//      strID = (String1D.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1D);
//        String1D = "";
//      }
//      strID = (String1E.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1E);
//        String1E = "";
//      }
//      strID = (String1F.substring(4, 6));
//      if (strID == "TG" || "DA" || "LL" || "NS" || "RS") {
//        dataFile.print(String1F);
//        String1F = "";
//      }

//    }
    else {
      File dataFile = SD.open("ES2.txt", FILE_WRITE);

      if (dataFile) {
        dataFile.print(dt);
        dataFile.print(" ");
        dataFile.print(tm);
        dataFile.print(msec);
        dataFile.print(",");
        dataFile.println(String1);
        Serial.print (String1);
//        dataFile.println(String1B);
        String1A = "";
        String1B = "";
        dataFile.close();
      }
    }
//  }
  string1Complete = false;
  }

}

//-----------------------------------------------------------------------------------------------------------------

void serial1Event() {
  while (Serial1.available()) {
    char inChar1 = (char)Serial1.read();
    inputString1 += inChar1;
    Serial1TimeOut = RxTimeOut;
    NewDataFlag1 = 1;

    if (NewDataFlag1 == 1) {
      string1Complete = true;
    }

  }
}
```

title: String Split Issue

Answers: 1

body:
I do not know what the “frequencies” have to do with your problem, but I
would bet that you would get more reliable results if you handle one
NMEA sentence at a time, instead of trying to handle six of them at
once, and hoping to get the right ones.

Below is a function that processes one complete sentence at a time. It
records the sentence to the SD file if its type belongs to a list of
“interesting” types you want to monitor:

```c++
// Sentence types that are to be recorded.
const char monitoredTypes[6][4] = {
    "GGA", "VTG", "ZDA", "GLL", "GNS", "GRS"
};

// Process a complete, CRLF-terminated NMEA sentence.
void processSentence(String &sentence) {

    // Sanity check.
    if (sentence.substring(0, 3) != "$GP") {
        Serial.print("WARNING: invalid sentence: ");
        Serial.print(sentence);
        return;
    }

    // Record the sentence if it has an interesting type.
    String type = sentence.substring(3, 6);
    for (int i = 0; i < 6; i++) {
        if (type == monitoredTypes[i]) {
            File dataFile = SD.open("GPS1.txt", FILE_WRITE);
            if (type == "GGA") {  // this type seems to be special
                dataFile.print(dt);
                dataFile.print(" ");
                dataFile.print(tm);
                dataFile.print(msec);
                dataFile.print(",");
            }
            dataFile.print(sentence);
            dataFile.close();
        }
    }
}
```

The way to use it is to buffer the incoming characters until you get a
complete sentence (identified by the final LF), then submit that buffer
to this function:

```c++
String buffer;

void loop() {
    while (Serial.available() > 0) {
        char c = Serial.read();
        buffer += c;

        // On end of sentence, process and clear the buffer.
        if (c == '\n') {
            processSentence(buffer);
            buffer = "";
        }
    }
}
```

Note that it wouldn't take too much work to get rid of the `String`
class and use plain C strings instead. Plain strings are way more memory
friendly.


body:
I'm currently trying to get an Arduino Zero to show up as a native USB MIDI device in my DAW (ableton). No matter what I try, I cannot get it to show up as a device in Ableton. I have previously used an arduino DUE for a similar project, but cannot get this to work the same. Is there something I'm missing to get the Zero to show up as a native USB Device?

Below is the code have written. I had assumed that the MIDIUSB library takes care of the arduino being recognised as a USB device.

    #include <MIDIUSB.h>

    const byte CHANNEL = 1;
    const byte OFFSET = 48;

    void setup(){}

    void loop()
    {
        delay(100);
        sendNoteOn(CHANNEL, 50 + OFFSET, 127);
        delay(100);
        sendNoteOff(CHANNEL, 50 + OFFSET, 0);
    }

    void sendNoteOn(byte channel, byte pitch, byte velocity)
    {
      midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOn);
    }

    void sendNoteOff(byte channel, byte pitch, byte velocity)
    {
      midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOff);
    }

title: Arduino Zero not recognised as MIDI device via native USB port

Answers: 1

body:
After extended trouble shooting and device manager fiddling, It turned out that Windows was auto installing the wrong (or partially wrong) drivers that made the native port not be recognised as a USB device. The device was detected as two different ports in the USB drivers, one of which had an error warning. I could still upload to it via either of the USB ports, just couldn't get it to be recognised as a MIDI device.

The solution was to:

 1.  completely uninstall the drivers from the device manager
 2.  uninstall the SAMD boards from the Arduino IDE
 3.  manually download [the drivers from github][1]
 4.  plug the arduino back in and install everything again as normal using those drivers

It now works like a charm.

  [1]: https://github.com/arduino/ArduinoCore-samd/tree/master/drivers


body:
The "Arduino language" (as [they call it](https://www.arduino.cc/reference/en/)) of the Arduino IDE 1 is obviously C++. Which C++ exactly?

I tried to figure it out myself (Arduino IDE 1.8.13 for Arduino Uno), but I can't conclude what C++ standard it supports.

From these tests, it seems to support C++14
* C++ 14 variable templates are supported (`template<typename T> constexpr T pi = T(3.1415926535);`)
* C++ 14 lambda captures are supported (`auto lambda = [value = 1] {return value;};`)

* C++ 14 deprecated is supported (`[[deprecated]]int fdep(){return 5;}`)

But not fully:

* C++ 14 digit separators are not supported (`int j = 2'000;`)

From these tests, it even seems to support some C++17:

* Nested namespace definitions are supported (`namespace X::Y {int func(){ return 1; } }`)

But also not fully:

* UTF-8 characters are not supported (`char x = u8'a';`)

If it partially supports everything, is there an overview like a list or table where I can look it up?

title: Which C++ standard does the Arduino language support?

Answers: 1

body:
The Arduino "language" is nothing more than a set of C++ functions and classes. It does not mandate any particular C++ standard.

The standard is dictated purely by the compiler that the core you are using happens to support (and is configured to use through command line flags).

Different cores use different compilers. Different versions of the same core use different compilers. Different compilers provide different C++ standard levels.

Most cores use GCC or some variant thereof. That could be anything from GCC 3.x.x through to the most recent release (whatever that is this week).

Currently the AVR core uses GCC 7.3.0 and is configured to use the gnu++11 standard by default (though avr-gcc and the associated libraries lack a full STL implementation). You can of course change that in the configuration files if you want.


body:
Pardon me, I am a novice programmer. I was trying to use the toInt() function for a std::string but I noticed that toInt() only works for the String class. So, I have an std::string sliderValue and wanted to convert it to the String class so I could use the toInt() function. [Here][1], I found a way that seemed to pacify Intellisense, vMicro, and building. I did:
```
String convertValue = strcpy(new char[sliderValue.length() + 1], sliderValue.c_str());
```
so I could do:
```
ledcWrite(ledChannel, convertValue.toInt()  * (10.24));
```
Is there a better way to do this or am I on point? Also, I'd love to get insight in what I'm doing, if possible. Thanks folks!

P.S. I looked up [this][2] here at arduino stackexchange, and it didn't seem to provide a solution specific to my question.

  [1]: https://www.techiedelight.com/convert-std-string-char-cpp/
  [2]: https://arduino.stackexchange.com/questions/56365/arduino-convert-stdstring-to-string

title: What's is the best way to convert std::string to String?

Answers: 1

body:
There is absolutely no need to use `String` (for anything, generally...). Instead you can either (if you have it) use `std::stoi()` or use `strtol()` on the `c_str` of the string.

```c++
ledcWrite(ledChannel, std::stoi(sliderValue)  * (10.24));
```

Or

```c++
ledcWrite(ledChannel, strtol(sliderValue.c_str(), NULL, 10)  * (10.24));
```

The former just converts into the latter anyway.


body:
My [Arduino Pro Micro][1] can source 500mA from 3.3V VCC, when it is USB powered.

The chip itself, is rated for 200mA, though, and its output pins for 20mA recommended, 40mA max.

I am looking to have 3 PWM outputs, though, each doing 120mA. The combined 360mA would be in-spec for VCC, but not for the chip.

Is there a buffer IC that I can use that will switch these loads at that current, and can keep up with a few hundred Hz PWM?

From what I've read, you can switch loads with discrete transistors, but these require extra components like resistors? Are there CMOS chips that will take the PWM signal and output it at 120mA?

I am looking to source the current, not sink it.

The load [in my application][2] are LEDs driven with constant-current drivers that are daisy chained. I just want to PWM the Vled supply so I can dim per channel, of the entire daisy chain.

**UPDATE:** I went with @Majenko's solution of pre-biased [DTB114EK][3]. Although it somewhat works, it seems to struggle to deliver 30mA out, even though it is rated at 500mA?

**UPDATE:** The [DTB113ZC][4] works better. Due to a lower bias resistor, I can get more current through it.

  [1]: https://wiki.keyestudio.com/Ks0249_keyestudio_PRO_MICRO_Development_Board
  [2]: https://electronics.stackexchange.com/questions/589973/tuning-a-constant-current-led-driver-per-channel
  [3]: https://www.mouser.ca/datasheet/2/348/dtb114ekt146-e-1872468.pdf
  [4]: https://fscdn.rohm.com/en/products/databook/datasheet/discrete/transistor/digital/dtb113zct116-e.pdf

title: Driving higher loads with PWM

Answers: 1

body:
Here is a part that will do the job for you, just 4 wires to connect.  Use your favorite search engine or go to your favorite china supplier and use this term: "Low Control High Voltage 12V 24V 36V switch Mosfet Module For Arduino Connect IO MCU PWM Control Motor Speed 3V 5V". You will get many choices several in the dollar range. It is opto isolated so that eliminates the ground connections etc. I have used them several times and they work nicely. [![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/ZtWJk.png


body:
Is anybody aware as to whether there are any modern microcontrollers that have hardware implementations of trigonometric functions? According to my understanding, modern CPUs have basic maths functions such as square roots and the trigonometric functions implemented in hardware to increase the speed and/or throughput of these maths functions. Do any widely used microcontrollers you know of have similar hardware implementations?

The reason I am asking this is because I want to know if it is feasible to implement more efficient trigonometric functions for specific use cases. On modern CPUs with the right compiler settings, it is almost always faster to use or derive from the built in trigonometric functions, rather than rolling your own software implementation specific to your problem.

title: Hardware implementation of trigonometric functions?

Answers: 1

body:
I do not know the answer to your main question, but I will try to answer
the underlying question:

> I want to know if it is feasible to implement more efficient
> trigonometric functions for specific use cases.

There are microcontrollers that do _not_ have hardware implementations
of trig functions, and that is the main point. The AVRs powering many
Arduinos are among them: they don't even have hardware floating point.
The libc provides implementations of the trig functions that are both
quite accurate (about 24 bits of accuracy) and very slow (about
100 µs for a `cos()` on an Uno).

There are also situations where you do not need that level of accuracy.
So yes, custom trig functions that hit the right balance between speed
and accuracy can be helpful on Arduinos. Note that the right balance is
project specific, so there is no one-size-fits-all, and rolling your own
can make sense.

For reference, I once wrote a fixed-point `cos()` accurate to
9.53 × 10<sup>−5</sup> that ran in 6.77 µs on average on
an Uno. I can provide a link if someone is interested. If you can do
better (faster at same accuracy, or more accurate at same speed) I
definitely would love to see that.


body:
I am building a model scale locomotive and therefore use Arduino for the DC motor, smoke generator, sound and lights. Can you help me with reviewing the circuit?

Power comes from rechargeable batteries (9.6V). This will supply the buck converter and the motor shield. Rest of circuit runs on 5V. A few MOSFETS regulate power for LEDs and smoke generator. MOSFET is overkill for this scale I know now. The locomotive has two parts: locomotive itself and the tender where the batteries and boards are put in. I just need to connect 5 cables for it to work.

Can you help reviewing if there are any errors / electrical shorts possibilities. Please don't add unnecessary complexity.

[![https://i.postimg.cc/tRP78kpY/Locomotive-circuit.png][1]][1]

  [1]: https://i.stack.imgur.com/AlPRA.jpg

title: Model locomotive circuit review

Answers: 0


body:
We have developed our board with PN5180 NFC but I cannot make it work properly. After I send RF_ON command I am stuck on STATE_CHANGE_IRQ_STAT while waiting for TX_RFON_IRQ_STAT but the state never changes. In this moment I can see sinus vawes on the oscilloscope. If I ignore it I will be stuck waiting for the RX_STATUS register to reflect the TRANSCEIVE_STATE. If I ignore both, the TX_RFON_IRQ_STAT appears after few SEND_DATA sequences but card cannot be read. Has anyone experience this?

    def init(self):

    # 1. Loads the ISO 15693 protocol into the RF registers
    self._send([LOAD_RF_CONFIG, 0x00, 0x80])

    # 2. Switches the RF field ON.
    self._send([RF_ON, 0x00])

    answer = self.read_irq_status_register()
    while ((TX_RFON_IRQ_STAT & answer) == 0):
      answer = self.read_irq_status_register()
      self.show_status(answer)

    return 1

title: NFC hang after RF_ON command

Answers: 1

body: The solution is that PN5180 simply cannot work without BUSY pin connected.


body:
I've been trying to host a BLE-server on my ESP32 with a custom service. I'm trying to read the service data in NodeRED, but the service IDs and custom characteristics don't show up in NodeRED whenever I import the scan results of my BLE input node in NodeRED.
The device and service both show up fine on Android using NRFtool:

[![enter image description here][1]][1]

However, in NodeRED, the device shows up and connects just fine, but none of the characterestics are displayed at NodeRED's end:

[![enter image description here][2]][2]

[![enter image description here][3]][3]

I'm using NodeRED version 1.2.9 with the [Generic BLE node][4]. And the ESP32 sample i'm using can be found [here][5].

I've also tried the BLE server examples included with the BLEDevice library with similar issues.
In addition to this: I'm not sure if this is just a typo in the node's error message, or if it's a typo in the node itself, but all mentions of the type "topic" are displayed as "tpoic" in NodeRED's debug log. Though i doubt this affects the functionality of the node in any way. Nowhere in my flow is there a mention of the keyword "tpoic".

[![enter image description here][6]][6]

Any suggestions as to how i could make my services show up in NodeRED would be appreciated.
Thank you.

  [1]: https://i.stack.imgur.com/IRkhL.jpg
  [2]: https://i.stack.imgur.com/LFEyV.jpg
  [3]: https://i.stack.imgur.com/nykiY.jpg
  [4]: https://flows.nodered.org/node/node-red-contrib-generic-ble
  [5]: https://github.com/LiveSparks/ESP32_BLE_Examples/blob/master/BLE_potentiometer/BLE_potentiometer.ino
  [6]: https://i.stack.imgur.com/sU76V.jpg

title: ESP32 BLE service not visible to Node-RED

Answers: 1

body: Turns out BlueZ on linux no longer supports ESP32 BLE devices. I tried the same code on a bluefruit M0 and it worked just fine.


body:
This comm sketch simply read incoming bytes from the UART 1 where a device is attached.
It works normally on a real Arduino device.
But on ESP32, it makes it continuously reboot with the following messages:

([UPDATE] Note that there is no reboot on ESP32 is I use Serial2 instead of Serial1)

```
9:13:19.676 -> ets Jun  8 2016 00:22:57
19:13:19.676 ->
19:13:19.676 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
19:13:19.676 -> configsip: 0, SPIWP:0xee
19:13:19.676 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
19:13:19.676 -> mode:DIO, clock div:1
19:13:19.676 -> load:0x3fff0018,len:4
19:13:19.676 -> load:0x3fff001c,len:1216
19:13:19.714 -> ho 0 tail 12 room 4
19:13:19.714 -> load:0x40078000,len:10944
19:13:19.714 -> load:0x40080400,len:6388
19:13:19.714 -> entry 0x400806b4
19:13:19.786 -> Yo! from serial UART 18/19
19:13:19.786 -> SbmDi⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮@D@⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
@%cGuru Meditation Error: Core  1 panic'ed (IllegalInstruction). Exception was unhandled.
19:13:19.823 -> Memory dump at 0x400e90f4: ffffffff ffffffff ffffffff
19:13:19.823 -> Core 1 register dump:
19:13:19.823 -> PC      : 0x400e90f8  PS      : 0x00060530  A0      : 0x800d1529  A1      : 0x3ffb1f80
19:13:19.823 -> A2      : 0x3ffbfe88  A3      : 0x3ffbfe6c  A4      : 0x0001c200  A5      : 0x0800001c
19:13:19.823 -> A6      : 0x00004e20  A7      : 0x00000000  A8      : 0x800d0c4f  A9      : 0x3ffb1f60
19:13:19.857 -> A10     : 0x3ffbfe6c  A11     : 0x3f40013b  A12     : 0x0800001c  A13     : 0x00000009
19:13:19.857 -> A14     : 0x00000009  A15     : 0x00000000  SAR     : 0x00000016  EXCCAUSE: 0x00000000
19:13:19.857 -> EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffbd
19:13:19.857 ->
19:13:19.857 -> ELF file SHA256: 0000000000000000
19:13:19.857 ->
19:13:19.857 -> Backtrace: 0x400e90f8:0x3ffb1f80 0x400d1526:0x3ffb1fb0 0x400860ed:0x3ffb1fd0
19:13:19.891 ->
19:13:19.891 -> Rebooting...

```

Here's my code:

```cpp
#include <Arduino.h>

#define SbmDisplaySerial Serial1

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  Serial.println("Yo v0.0.1! from serial UART 18/19");

  SbmDisplaySerial.begin(9600, SERIAL_8N1);//, 16, 17);

  Serial.print("SbmDisplaySerial is ");
  Serial.println(SbmDisplaySerial);
}

int _loop = 1;

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Loop #"); Serial.println(_loop++);
  delay(1000);

  if (!SbmDisplaySerial.available()) {
    delay(2000);
    Serial.println("No byte avail from the UART, looping…");
    return;
  }

   int b = 0;

   Serial.print("Synching with message limit (waiting for 0xA5 (165) header byte): ");
   int i=0;
   do {
     delay(10);
     b = SbmDisplaySerial.read();
     Serial.print(b);
     Serial.print(" ");
     if (i8==0) Serial.println();
      i++;
   }
   while(b!=0xa5);

  Serial.println("Ok, packet started!");
  Serial.print("Received bytes: ");
  Serial.print(b);
  Serial.print(" ");

  int soc = 0;
  int voltage = 0;
  int current = 0;
  int capacity = 0;

  for(int i=1; i<16; i++) {
    b = SbmDisplaySerial.read()&0xff;

    Serial.print(b);
    Serial.print(" ");

    switch(i) {
      case  0: Serial.print("Header byte 0xA5");
        voltage = 0;
        current = 0;
        capacity = 0;
      break;
      case  1: soc = b; Serial.print("(SoC: ");  Serial.print(soc); Serial.print("%) "); break;

      case  2: voltage = b<<8; break;
      case  3: voltage |= b;  Serial.print("(");  Serial.print(float(voltage)*0.01); Serial.print("V) "); break;

      case  4: capacity = b<<24; break;
      case  5: capacity = b<<16; break;
      case  6: capacity = b<<8; break;
      case  7: capacity |= b;  Serial.print("(");  Serial.print(float(capacity)*0.001); Serial.print("A.h) "); break;

      case  8: current = b<<24; break;
      case  9: current = b<<16; break;
      case 10: current = b<<8; break;
      case 11: current |= b;  Serial.print("(");  Serial.print(float(current)*0.001); Serial.print("A) "); break;

      //case 12: current = b<<8; break;
      //case 13: current = b<<8; break;
      //case 10: current |= b;  Serial.print("(TOA: ");  Serial.print(float(current)*0.001); Serial.print("Seconds) "); break;
    }

    if (!SbmDisplaySerial.available()){
      delay(2000);
      Serial.print(" No more byte prior reaching 16 bytes, looping…");

      break;
    }
  }

  Serial.println("Waiting for next packet");
  delay(10000);

}
```
*[UPDATE]*
When ran on Arduino, I get typical logs as follows:

```
11:20:18.217 -> Yo v0.0.1! from serial UART 18/19
11:20:18.217 -> SbmDisplaySerial is 1
11:20:18.217 -> Loop #1
11:20:19.204 -> Synching with message limit (waiting for 0xA5 (165) header byte): 0
11:20:19.204 -> 0 0 0 0 165 Ok, packet started!
11:20:19.275 -> Received bytes: 165 28 (SoC: 28%) 4 251 (12.75V) 0 0 54 248 (14.07A.h) 255 255 0 0 (0.00A) 0 0 0 0 Waiting for next packet
11:20:29.263 -> Loop #2
11:20:30.266 -> Synching with message limit (waiting for 0xA5 (165) header byte): 0
11:20:30.266 -> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 165 Ok, packet started!
11:20:30.508 -> Received bytes: 165 28 (SoC: 28%) 4 251 (12.75V) 0 0 182 0 (46.59A.h) 0 0 0 0 (0.00A) 0 0 0 0 Waiting for next packet

```

title: Serial comm UART1 works on Arduino but makes ESP32 continuously reboot

Answers: 2

body: Here is what I've ended up with: I dropped Serial1 as I did not find anyway to make it run and I switched to Serial2, where everything works as expected.

body:
```c++
#define SER1_RX 35
#define SER1_TX 32

void setup()
{
    Serial.begin(115200);      //
 Serial.setDebugOutput(1);

    // For Serial1, be sure to set the communication port.
 Serial1.begin(115200, SER1_RX, SER1_TX); // set the communication port
}
```


body:
I am working on servo motors control through serial communication protocol, I am sending data from Simulink to arduino and vice versa, The problem I am getting is that once I open Simulink Servo motors start turning while no command is sent or received from both, I tought that Simulink is initializing (reseting) arduino, so I decided to add a capacitor between Gnd & reset (I also tried with a resistor between 5v & reset), It actually works when I try to use Arduino IDE, Arduino is not reseting, but When i use it with Simulink it doesn't make change, Servo motors still turning randomly (I think that when I start or close simulation, Servo Are going to their initial position, I am not sure). I tried to add initial Position in Setup() function but in vain, It doesn't make sens!
I tried using different arduino cards (MEGA, ESP32...Etc.) but in vain.

Does anyone have an idea about how to figure out this problem?
Here is Simulink control code : & Arduino code :

```

#include <SCServo.h>
SCSCL sc;

//Estructura Union
typedef union {
  float number;
  uint8_t bytes[4];
} valor;
valor velocidad;

unsigned long timeold;
int vel = 0;
float value;
void setup() {

  Serial1.begin(1000000);
  sc.pSerial = &Serial1;
  Serial.begin(9600);
}

void loop() {
  //Pregunta si tenemos un dato a recibir
  if (Serial.available() > 0) {
    value = recepcion();
  }

  //Transforma el valor del voltaje (0-5) a velocidad
  vel = map(value, 0, 5, 0, 1023);
  //Activa el motor dirección Backward con la velocidad
  sc.WritePos(3,  value, 0);

  velocidad.number = sc.ReadPos(3);

  Serial.write('V');
  for (int i = 0; i < 4; i++) {
    Serial.write(velocidad.bytes[i]);
  }
  Serial.write('\n');
  delay(50);
}

//Recibir Flotante
float recepcion() {
  int i;
  valor buf;
  for (i = 0; i < 4; i++)
    buf.bytes[i] = Serial.read();
  return buf.number;
}
//Función para la lectura del encoder

```

[![enter image description here][1]][1]

Thank you !

  [1]: https://i.stack.imgur.com/yBA2S.png

title: Simulink resets arduino

Answers: 0


body: I have made an irrigation system using Arduino. Timer program is based on comparing the previous Millis() and current Millis(). I want to know the chance for error when the currentMillis() overflows and start from zero after 50 days, while the previous Millis() stored in the variable remains as a larger value.

title: Millis() based timer program for 24x7 usage in Arduino

Answers: 0


body:
I'm trying to read a Ant BMS 32H with a ESP8266 and a HC05 module.
BMS is sending 146 bytes when asking for these by sending DB DB 0 0 0 0 (HEX)
I did test with my android phone and the app 'Serial Bluetooth Terminal' and I receive/see the 146 bytes.
When doing this with the ESP8266/HC05 I only receive 63 bytes.
I saw already that I shouldn't use delays before reading the serial buffer, as this could cause buffer overflows.

I have no clue on what the reason could be ... hope someone has some more knowledge then I do ...
Please see my code I use ( I didn't post the Process_Data() routine as this one is called afterwards )
Initial I tried without the cosmetic visualization ( extra lines of code taking cpu cycle to execute) and it give the same result

The result I receive :

    ---------------------------------------------------
    Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
    00:AA 01:55 02:AA 03:FF 04:02 05:7B 06:08 07:43 08:08 09:43
    10:08 11:47 12:08 13:41 14:08 15:3B 16:08 17:45 18:08 19:41
    20:08 21:46 22:08 23:43 24:08 25:41 26:08 27:43 28:08 29:46
    30:08 31:44 32:08 33:41 34:08 35:49 36:08 37:41 38:08 39:43
    40:08 41:42 42:08 43:3F 44:08 45:3F 46:08 47:46 48:08 49:44
    50:08 51:4F 52:08 53:38 54:08 55:3E 56:08 57:47 58:08 59:47
    60:08 61:45 62:08
    Bytes received : 63

My .ino :

    #include <SoftwareSerial.h>;
    SoftwareSerial EEBlue(12, 13); // RX | TX // AT command mode
    // byte message[] = {0x5A, 0x5A, 0x5A, 0x00, 0x00, 0x5A, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A };
    byte message[] = {0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 };
    byte bms[147]; // 82 + 65 = 147 bytes
    int i;
    int x;
    int highbyte, lowbyte;
    uint16_t a16bitvar;
    unsigned int BattSOCG;
    float BattPowerG;

    void setup()
    {
      Serial.begin(115200);
      delay(500);
      EEBlue.begin(38400);  //38400 Baud for AT commands , set by command : AT+UART=38400,1,0 or AT+UART=9600,1,0
      delay(500);
      Serial.println();
      Serial.println("Serial and Bluetooth started.");
      Serial.println(); Serial.println("");
    }

    void loop()
    {
      AskBMSData();
      GetBMSData();
      Process_Data();
      delay(3000);
    }

    // ---------------------------------------------------------
    void AskBMSData()
    {
      Serial.print("Sending request ("); Serial.print(sizeof(message)); Serial.print(" bytes) : ");
      for (i=0; i<sizeof(message); i++)
      {
        Serial.print(message[i], HEX);
        Serial.print(" ");
      }

      EEBlue.write(message, sizeof(message));
    }

    void GetBMSData()
    {
      Serial.println(" Answer :");
      // Feed any received bluetooth data to Terminal.
      i=0;
      while (EEBlue.available()) {
        bms[i]= EEBlue.read();
        if(i<10) Serial.print("0");
        Serial.print(i); Serial.print(":");
        if(bms[i]<16) Serial.print("0");
        Serial.print(bms[i], HEX);
        Serial.print(" ");
        x = (i+5)/10; x = 10*x-1; if(i==x) Serial.println();
        i++;
      }
      Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
    }

    // --------------------------------------------------------

**Code changed based on Chrisl's response to :**

    void GetBMSData()
    {
      Serial.println(" Answer :");
      // Feed any received bluetooth data to Terminal.
      i=0;
      if (EEBlue.available()) {
          while (i<146) {
            bms[i]= EEBlue.read();
            i++;
            }
      }

      for (z=0; z<i; z++) {
        if(z<10) Serial.print("0");
        Serial.print(z); Serial.print(":");
        if(bms[z]<16) Serial.print("0");
        Serial.print(bms[z], HEX);
        Serial.print(" ");
        x = (z+5)/10; x = 10*x-1; if(z==x) Serial.println();
      }
      Serial.println(); Serial.print("Bytes received : ");Serial.println(i);Serial.println();
    }

with result :

    ---------------------------------------------------
    Sending request (6 bytes) : DB DB 0 0 0 0  Answer :
    00:AA 01:55 02:AA 03:FF 04:02 05:71 06:08 07:23 08:08 09:23
    10:08 11:26 12:08 13:21 14:08 15:1B 16:08 17:25 18:08 19:1E
    20:08 21:27 22:08 23:24 24:08 25:1E 26:08 27:23 28:08 29:27
    30:08 31:25 32:08 33:1F 34:08 35:28 36:08 37:21 38:08 39:22
    40:08 41:22 42:08 43:1C 44:08 45:23 46:08 47:28 48:08 49:26
    50:08 51:31 52:08 53:17 54:08 55:1E 56:08 57:28 58:08 59:29
    60:08 61:25 62:08 63:FF 64:FF 65:FF 66:FF 67:FF 68:FF 69:FF
    70:FF 71:FF 72:FF 73:FF 74:FF 75:FF 76:FF 77:FF 78:FF 79:FF
    80:FF 81:FF 82:FF 83:FF 84:FF 85:FF 86:FF 87:FF 88:FF 89:FF
    90:FF 91:FF 92:FF 93:FF 94:FF 95:FF 96:FF 97:FF 98:FF 99:FF
    100:FF 101:FF 102:FF 103:FF 104:FF 105:FF 106:FF 107:FF 108:FF 109:FF
    110:FF 111:FF 112:FF 113:FF 114:FF 115:FF 116:FF 117:FF 118:FF 119:FF
    120:FF 121:FF 122:FF 123:FF 124:FF 125:FF 126:FF 127:FF 128:FF 129:FF
    130:FF 131:FF 132:FF 133:FF 134:FF 135:FF 136:FF 137:FF 138:FF 139:FF
    140:FF 141:FF 142:FF 143:FF 144:FF 145:FF
    Bytes received : 146

title: ESP8266 with HC05 : expecting to receive more bytes then the 63 received

Answers: 1

body:
I see 2 things, that might give you problems. First the one with a higher chance of being the important point:

You use

    while (EEBlue.available())

in your `GetBMSData()` function. With serial (and especially over a packeted protocol like bluetooth) the sender might introduce pauses in the transmission of the data (for example when it needs to wait for more data, doing other tasks than sending or when a bluetooth packet ends and a new one must be send). You cannot control if and when these pauses happen. They might be big enough so that your `while()` loop can clear the internal buffer of the `SoftwareSerial` library without already having received the full message.

With serial you cannot think of a message as one block of data, which arrives together at the same time. You need to account for it to take its time. For example you could loop inside that function, until you have received the full message. That would fit to your current code structure. Something like this:

    while(i<146){
      if(EEBlue.available()){
        bms[i]= EEBlue.read();
        i++;
      }
    }

Note: If for whatever reason less than the expected number of bytes is send, this code will block forever - or until it received that many bytes.

Or - if you want to do it non-blocking (also rewriting the rest of the code), then you could just allocate a buffer big enough for the whole message and only place the bytes as they arrive inside that buffer. The rest (like sending the data out over `Serial` can then be done, when you have all the data bytes of the message. In this case you don't need a `while` loop, since the `loop()` function already handles the looping. You just test on very loop iteration if data is available and read it. After you read a byte you test for the message being complete. If yes, do the printing and processing.

---

The second problem is not that probable, but I still want to include that here. You are doing quite some printing inside the `while` loop, printing at least 6 bytes for every received byte. Serial can take some time and if it takes to long you can fill up your buffer in the background, effectively loosing data. I would suggest using the `while` loop to just `read()` the bytes and save them in your array. The printing can then be done after the full message was received. For the human reading the Serial printout it will not be different, but you can prevent losing data this way.


body:
I am testing on an Arduino UNO. I want to use timer1 and interrupts to create various LED patterns. The LEDs may span multiple ports i.e PORTB and PORTD. I want to use a "volatile uint8_t*" pointer to store whether to toggle a pin on PORTB or PORTD i.e have the pointer store &PORTB or &POINTD. And then use it as necessary. However, once set, I cannot seem to be able to change the pointer in the loop.

Some more details:
I'm using timer1 in CTC mode (clear on compare match) and making use of both OCR1A and OCR1B interrupts.
When output compare A interrupt matches, the led is turned on and a flag is set for the main loop to change leds.
When output compare B interrupt matches, the led is turned off.
The switch statement works and the led pins can be changed i.e next_led and current_led, however, the next_port and current_port statements are ignored in the main loop.
The led pin change works when changing from case 3 to case 1 (when they are both PORTB), but when changing the next_port variable to PORTD this is completely ignored.

At the very beginning of the code, if I initialize current_port and next_port with &PORTD, then just PORTD led will light up and the main loop will not change the current_port and next_port variable to &PORTB.

I have tried using volatile uint16_t* for the next_port and current_port and that doesn't work, either.

What am I doing wrong?

```
int red_led = 9;    //PORTB 1
int green_led = 10; //PORTB 2

int led3 = 5;       //PORTD 5

volatile uint8_t current_led = 1; //port number of led
volatile uint8_t next_led = 1;

volatile uint8_t *current_port = &PORTB;
volatile uint8_t *next_port = &PORTB;

int counter = 0;
volatile int change_led_flag = 0;
volatile uint8_t led_state = 1;

uint16_t ocr1a_val = 10000-1; //determines period. 16MHz clock, Prescaler=8, 10000-1 ticks = 5ms period (200Hz)
uint16_t ocr1b_val = 9900-1; //determines duty cycle (99% for 10000 ticks)

void setup() {
  pinMode(red_led, OUTPUT);
  pinMode(green_led, OUTPUT);
  pinMode(led3, OUTPUT);

  TCCR1A = 0;
  TCCR1B = 0;

  //set CTC mode
  TCCR1B |= (1<<WGM12);

  //set OCR1A value
  OCR1A = ocr1a_val;
  //set OCR1B value
  OCR1B = ocr1b_val;

  //set pre-scaler to 8
  TCCR1B |= (1 << CS11);

  //enable output compare interrupts
  TIMSK1 |= (1 << OCIE1A);
  TIMSK1 |= (1 << OCIE1B);

  sei();
}

void loop() {
  if(change_led_flag == 1){
  change_led_flag = 0;
  current_led = next_led; //set the current led to what was just turned on
  current_port = next_port; //this statement doesn't do anything.
  switch (led_state) {
    case 1:
      led_state = 2;
      next_led = 2;
      next_port = &PORTB; //this statement doesn't do anything
      break;
    case 2:
      led_state = 3;
      next_led = 5;
      next_port = &PORTD; //this statement doesn't do anything
      break;
    case 3:
      led_state = 1;
      next_led = 1;
      next_port = &PORTB; //this statement doesn't do anything
      break;
    } //end switch statement
  } //end if

} //end loop()

//turn on next_led and set change_led_flag
ISR(TIMER1_COMPA_vect){
  *next_port |= (1 << next_led); //turn on led
  change_led_flag = 1; //set flag to update next led
}

//turn off current_led
ISR(TIMER1_COMPB_vect){
  *current_port &= ~(1 << current_led); //turn off led
}

```

title: Cannot change pointer for port in main loop

Answers: 1

body:
I don't *know* this is your problem, but it is *a* problem in any case.
The pointer itself, not just what it points to, would also need to be volatile qualified. That is:

```c++
volatile uint8_t *volatile current_port = &PORTB;
volatile uint8_t *volatile next_port = &PORTB;
```

The `volatile` after the pointer declarator (the `*`) determines the `volatile` quality of the pointer itself.  The `volatile` that you already had prior to the declarator is just qualifying what is pointed-to, the port in this case, which is needed for similar reasons.

Without the pointer itself being `volatile`, you can't expect to changes to it to be reflected correctly between the ISR contexts and the normal main line of execution that runs `setup`, `loop` and and most everything else.  The compiler/optimizer may assume since it can't see any way to get to code that can change the value that the value is therefore not changing.  ISR dispatches are outside its field of view.

Also in the when you update `next_port` outside of the ISR, you probaly should make sure interrupts are off while you update it:

```c++
noInterrupts();
next_port = &PORTB;
interrupts();
```

Because the pointer value is a two-byte address, if you don't disable the interrupts while assigning it your ISR can be dispatched midway through the assignment when the pointer object isn't yet valid.  I say *should* above, because in your situation the addresses that happen to be used for ports may all have the same upper byte value. It's a good habit to be in regardless.


body:
**Theoretical Q**

I'm having some trouble when using a referenced variable in a class.

`Class A` have an `int a=0`. `Class B` has an instance of `Class A`, and referencing `int &a=A.a`, and in the same manner `Class C` has an instance of `Class B` and `int &a=B.a`. Code crashed when trying to update `a` variable when using C instance.

**Relvant Example**

I'm creating a library for TFT+Touch 2.4 screen, to handle buttons more easily.

Libraries `XPT2046_Touchscreen` and `Adafruit_ILI9341` are included here, but initiated in main `.ino` file for easier handling in `loop` and more control in main code.

**1) `MessageTFT`**

A "basic" class was created, called `MessageTFT`. This class creates the graphics, and stores its geometrical properties and color as shown below.

**2) `ButtonTFT`**

`ButtonTFT` based on `MessageTFT` adding touch capabilities to it. Its geometrical and color parameters are referenced to `MessageTFT`. When creating a `button` instance, user defines its properties but, actually it is referenced to `MessageTFT`.

`ButtonTFT` and `MessagesTFT` works as expected. For example a button is defined in `.ino`:

    ButtonTFT butt;

and defined in `void setup()`:

      butt.a = 200;
      butt.b = 60;
      butt.xc = tft.width() / 2;
      butt.yc = tft.height() - butt.b / 2;
      butt.txt_size = 1;
      butt.face_color = ILI9341_CASET;
      butt.txt_color = ILI9341_DARKGREY;
      butt.border_color = ILI9341_MAGENTA;
      butt.roundRect = false;
      butt.createButton("Press!");

and in `void loop()`:

      if (ts.touched())
      {
        TS_Point p = ts.getPoint();
        if (butt.checkPress(p))
          {
            Serial.print("Pressed");
          }
      }

**3) `buttonArrayTFT`**

Evolving to `buttonArrayTFT`, which spreads up to 8 buttons x and y centered on screen. Here again using same way to reference relevant properties (in `buttonArrayTFT` each button's size and position are not defined by user, but calculated to optimize size and position). Now variable are referenced to a `ButtonTFT` instance, for example `&txt_size = _button0.txt_size` as shown below.

Since `txt_size` is common for all button members in that array of buttons, it is referenced for all buttons later in code.

Also `buttonArrayTFT` works as expected, when defining its instance as:

    char *a[] = {"All Windows", "Saloon", "Room", "Specific"};
    buttonArrayTFT mainWindows;

and created:

      mainWindows.create_array(4, 1, a);

as a 4X1 button array with text for each button as in `a`.

**The Problem (code crashes)**

when trying to pass a value for any of referenced parameter ( taking `txt_size` as an example ):

    mainWindows.txt_size = 3;          // <----- This
    mainWindows.create_array(4, 1, a);

While when doing same thing when initiating a button (see up ), I use same way to update button's text size (which is refenced to `MessageTFT` ).

What may be the reason for that ??

Guy

`.h` file:

    #ifndef TFT_GUI_h
    #define TFT_GUI_h

    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ILI9341.h>
    #include <XPT2046_Touchscreen.h>

    /* Screen calibration */
    #define TS_MIN_X 350
    #define TS_MIN_Y 350
    #define TS_MAX_X 3800
    #define TS_MAX_Y 3800
    /* ~~~~~~~~~~~~~~~~~ */

    /* For Wemos Mini and TFT screen 2.4" */
    #define TFT_CS D0
    #define TFT_DC D8
    #define TFT_RST -1
    #define TS_CS D3
    /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

    const uint8_t _pos_corr_factor_x = 3;
    const uint8_t _pos_corr_factor_y = 4;

    extern XPT2046_Touchscreen ts; /* Touch screen */
    extern Adafruit_ILI9341 tft;   /* Graphics */

    class MessageTFT
    {
    public:
      int xc = 0;
      int yc = 0;
      uint8_t a = 0;
      uint8_t b = 0;
      uint8_t txt_size = 3;
      uint8_t border_thickness = 1;
      char txt_buf[20];
      bool roundRect = true;
      uint8_t screen_rotation = 0;
      uint16_t face_color = ILI9341_GREENYELLOW;
      uint16_t txt_color = ILI9341_BLACK;
      uint16_t border_color = ILI9341_RED;
      Adafruit_ILI9341 *TFT[1];

    public:
      MessageTFT(Adafruit_ILI9341 &_tft = tft);
      void createMSG(char *txt);
      void clear_screen(uint8_t c = 0);

    private:
      void _put_text(char *txt);
      void _drawFace();
      void _drawBorder();
    };

    class ButtonTFT
    {
    public:
      /* Following vars belong to MSG class*/
      MessageTFT MSGwindow;
      int &xc = MSGwindow.xc;
      int &yc = MSGwindow.yc;
      uint8_t &a = MSGwindow.a;
      uint8_t &b = MSGwindow.b;
      uint8_t &txt_size = MSGwindow.txt_size;
      uint8_t &screen_rotation = MSGwindow.screen_rotation;
      uint16_t &face_color = MSGwindow.face_color;
      uint16_t &txt_color = MSGwindow.txt_color;
      uint16_t &border_color = MSGwindow.border_color;
      bool &roundRect = MSGwindow.roundRect;
      char *txt_buf = MSGwindow.txt_buf;
      /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

      XPT2046_Touchscreen *TS[1];

    public:
      ButtonTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void createButton(char *txt);
      bool wait4press();
      bool checkPress(TS_Point &p);

    private:
      int _tft_x, _tft_y;

    private:
      void _put_text();
      void _press_cb();
      /* fucntions below converts touchscreen values to TFT coordinates */
      void _conv_ts_tft(TS_Point &p);
      bool _check_press_geometry(TS_Point &p);
      int _TS2TFT_x(int px);
      int _TS2TFT_y(int py);
    };

    class buttonArrayTFT
    {
    public:
      buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void create_array(uint8_t R, uint8_t C, char *but_txt[]);
      uint8_t checkPress(TS_Point &p);

    public:
      uint8_t &txt_size = _button0.txt_size;
      uint16_t &txt_color = _button0.txt_color;
      uint16_t &border_color = _button0.border_color;
      bool &roundRect = _button0.roundRect;
      int shift_array = 0;

    private:
      ButtonTFT _button0;
      ButtonTFT _button1;
      ButtonTFT _button2;
      ButtonTFT _button3;
      ButtonTFT _button4;
      ButtonTFT _button5;
      ButtonTFT _button6;
      ButtonTFT _button7;
      ButtonTFT *_buttons[8] = {&_button0, &_button1, &_button2, &_button3,
                                &_button4, &_button5, &_button6, &_button7};

    private:
      uint8_t _num_items = 0;
    };

    #endif

**Edit1: How Constructors are defined in `.cpp` file**

    MessageTFT::MessageTFT(Adafruit_ILI9341 &_tft)
    {
      TFT[0] = &_tft; // <--- stored in a pointer
    }

and

    ButtonTFT::ButtonTFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft) : MSGwindow(_tft)
    {
      MSGwindow.TFT[0] = &_tft;
      TS[0] = &_ts;
    }

and

    buttonArrayTFT::buttonArrayTFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft)
        : _button0(_ts, _tft), _button1(_ts, _tft), _button2(_ts, _tft),
          _button3(_ts, _tft), _button4(_ts, _tft), _button5(_ts, _tft),
          _button6(_ts, _tft), _button7(_ts, _tft)
    {
      _button0.MSGwindow.TFT[0] = &_tft;
      _button0.TS[0] = &_ts;
    }

title: Failure using references variables in classes

Answers: 1

body:
I'm not sure what value this is going to have for Arduino users, but here goes. Your question seem to be an over-complicated form of this the following:

*My code:*
```c++
struct MessageTFT {uint8_t txt_size = 3;};

struct ButtonTFT {
  MessageTFT MSGwindow;
  uint8_t &txt_size = MSGwindow.txt_size;
};

struct buttonArrayTFT {
  uint8_t &txt_size = _button0.txt_size;
  ButtonTFT _button0;
};

buttonArrayTFT bat;

void setup() {
  Serial.begin(9600);
  Serial.println(F("\n\n\nStart."));
}

void loop() {
  Serial.println(bat.txt_size++, DEC);
  delay(1000);
}
```

My question:

*Why does this crash? ...or not print the correct value? or whatever.*

I don't *think* I'm straw-manning (for lack of better term) your question.  But, the question is kind of a mess, so this a best-effort response to it.
If I've clarified the question to the point of being off-topic, so be it. If I do have the correct distillation, if nothing else what people can get out of this is that your questions here can usually be made simpler.

The declared order of members in a class is relevant to the order of initialization; there's more to it than just that. In any case, `_button0` has not been initialized prior to your `uint8_t &txt_size = _button0.txt_size;` The mechanism underlying a member reference in a class is basically that of a pointer.  You are essentially copying an uninitialized pointer out of `_button0` and into the `txt_size` member of `buttonArrayTFT`; that is the `uint8_t &txt_size = MSGwindow.txt_size` has not yet been executed.

You can fix this by doing nothing more than reordering the members like so:

```c++
struct buttonArrayTFT {
  ButtonTFT _button0;
  uint8_t &txt_size = _button0.txt_size;
};
```

Now `uint8_t &txt_size = MSGwindow.txt_size;` in `ButtonTFT` executes prior to `uint8_t &txt_size = _button0.txt_size;` in `buttonArrayTFT`.

This will fix the problem as I've presented. Should you do this? I'm not sure. But then that's not what was asked anyway. Still, you may be better served by getting rid reference members or converting them to inline functions that return a reference type. Or any number of other strategies.

At a minimum this is a problem your code has.


body:
I have a very simple routine that lights up the built-in LED (pin 13) when a system tick timer fires off its interrupt.

I override the weak reference to `int sysTickHook(void)` found in `hooks.c`. I found that in generalfor this to work I need to use `extern "C"` linkage

The part that is bewildering is that this interrupt fires off fine **without** `extern "C"` **if** there are the comments above it as shown below. This is the minimal reproducible example I can find.  Can someone explain this?

I'm using the plain old Arduino IDE 1.8.16.

```c
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- if you remove this line sysTickHook will not be called
// extern "C" -- if you remove this line sysTickHook will not be called
int sysTickHook()
{
  digitalWrite(13,HIGH);
  return 0;
}
```

title: Comments change compiled behavior (sysTickHook weak reference override)

Answers: 1

body:
The problem is the preprocessor in the IDE. It's not clever enough to work out the `extern "C"` when adding function prototypes.

With your comments you end up with:

```c++
#include <Arduino.h>
#line 1 "/home/matt/t/t.ino"
#line 1 "/home/matt/t/t.ino"
void setup();
#line 6 "/home/matt/t/t.ino"
void loop();
#line 10 "/home/matt/t/t.ino"
 extern "C" int sysTickHook(); // << The extern gets added here from the comment
#line 1 "/home/matt/t/t.ino"
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

// {          -- if you remove this line sysTickHook will not be called
// extern "C" -- if you remove this line sysTickHook will not be called
int sysTickHook()
{
  digitalWrite(13,HIGH);
  return 0;
}
```

It finds the `extern` in the comment and thinks it's real code. If you remove the comment markers it ends up with broken code, as you have a stray `{` in there. If you remove the comments entirely you end up with the function in the C++ linkage, which changes the function name internally and doesn't then override the weak function. The same happens if you remove just the first comment.

Basically having those comments breaks the preprocessor in such a way that it works.  The proper way of doing it is:

```c++
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {}

extern "C" {
  int sysTickHook()
  {
    digitalWrite(13,HIGH);
    return 0;
  }
}
```


body:
I have a class with 12 instances of a button, to create a keypad( meaning that this is the only case I use 12 instances). But this class can be just a button array of any other number between 1-12. I'm looking for a way to minimize class overhead of 12 instances, when I most of the time use much less.

'.h' file:

    class buttonArrayTFT
    {
    public:
      buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void create_array(uint8_t R, uint8_t C, char *but_txt[]);
      uint8_t checkPress(TS_Point &p);

    public:

    protected:
      ButtonTFT _button0;
      ButtonTFT *_buttons[12] = {&_button0, &_button1, &_button2, &_button3,
                                 &_button4, &_button5, &_button6, &_button7,
                                 &_button8, &_button9, &_button10, &_button11};
    private:
      ButtonTFT _button1;
      ButtonTFT _button2;
      ButtonTFT _button3;
      ButtonTFT _button4;
      ButtonTFT _button5;
      ButtonTFT _button6;
      ButtonTFT _button7;
      ButtonTFT _button8;
      ButtonTFT _button9;
      ButtonTFT _button10;
      ButtonTFT _button11;

    private:
      uint8_t _num_items = 0;
    };

title: Instances of a class inside another class - is there a way to control the amount?

Answers: 4

body:
You can use a *template* class to provide compile time parameters to your class to tune it. This is most often used in the context of providing a *type* for the class to operate on. However it's not limited to that. It's also often used to provide a storage size or other similar constant to the class.

They kind of work like preprocessor macros. You specify a token in the class and then give that token a value when you instantiate an object. That token can then be used all over the place in your class.

In your case you can provide the number of elements in your array of buttons as a template variable, for example (note: untested):

```c++
template <int N> class buttonArrayTFT {
    protected:
        ButtonTFT _buttons[N];
    public:
        void doSomething();
};

template <int N> void buttonArrayTFT::doSomething() {
    for (int i = 0; i < N; i++) {
        _buttons[i].doSomethingOnAButton();
    }
}
```

Of course you have to treat your objects a little differently since you can't make an array of pointers to predefined objects any more. Instead just a simple array of objects should be enough.

You then instantiate your class passing the number of elements you want:

```c++
// Array of 12 buttons
buttonArrayTFT<12> myButtons;
// and do something
myButtons.doSomething();
```

body:
As pointed out in a comment on your original question, a **template** is likely the best solution.

Templates allow you to write highly flexible code. I won't explain why; that's something that goes a little beyond the actual question. However, the following will show that you can create a template that means you can create a `buttonArrayTFT` class with *N* number of `buttonTFT` elements, so long as *N* is known at compile time. The [link given as  a comment][1] talks describes various aspects of templates but does not necessarily explain how to string it all together.

From the section **Non-type parameters for templates**, you will see that you can specify an integer as a parameter for creating *N* elements of an array member variable.

But what about the *type parameter, T*? You can simply omit it. You don't actually have to create a template for a *type*.

In your *.h* file:
```c++
template <uint8_t ARRAY_SIZE>
class buttonArrayTFT
{
public:
// One thing to remember about templates: you have to pack the definition
// into the header file with the declaration to avoid all manner of headaches.

    buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft)
    {
    // Perhaps this is a good opportunity to check that the specified
    // size of the array is sensible, i.e. not zero and no more than 12.
        if ((ARRAY_SIZE == 0) || (ARRAY_SIZE > 12))
        {
            // decide how you want to handle this problem
        }
            // Add the rest of your constructor here
    }

    void create_array(uint8_t R, uint8_t C, char *but_txt[]);
    uint8_t checkPress(TS_Point &p);

    // This little piece of magic allows you to access buttonTFT 'x' of the
    // private _buttonArray as if a buttonArrayTFT class was an array
    buttonTFT &operator[](uint8_t index)
    {
    // Check that 'index' is a valid element in the array
        if (index > _num_items)
        {
            // decide how you want to handle this problem
        }
        return _buttonArray[index];
    }
private:
    buttonTFT _buttonArray [ARRAY_SIZE];
    // I recommend making this constant
    const uint8_t _num_items = ARRAY_SIZE;
};
```
I shall leave it up to you to sort out your privates, publics and protecteds, and I have left out `ButtonTFT _button0;` to keep you on your toes.

You'll also notice that the array is private, as before, but there is now no array-of-pointers-to-buttons. This is because there is no need; the magic `buttonTFT &operator[](int index)` allows you to access array elements directly.

In your *.ino* file, or as appropriate, you use the following code to create and then wield the class:
```c++
buttonArrayTFT<4> myFourButtonArray(/* constructor arguments as required*/);
buttonArrayTFT<12> myTwelveButtonArray(/* constructor arguments as required*/);
```
This gives you two instances of the class, with the respective number of `buttonTFT` elements! You can now access specific buttons using the following code:
```c++
myFourButtonArray[0];    // Returns a reference to the first buttonTFT
myTwelveButtonArray[10]; // Returns a reference to the eleventh buttonTFT
myFourButtonArray[n]     // Returns a reference to the 'n+1'th buttonTFT
```
On the assumption that the `buttonTFT` class has some kind of 'read' function that returns a TRUE or FALSE for the status of the button, you can write:
```c++
if (myFourButtonArray[0].read())
{
    // executed if the button is ON
}
else
{
    // executed if the button is OFF
}
```

**A NOTE ON CONST-NESS:**

The overloading of `operator[]`, while wonderfully magic, is open to abuse. However, this is no different from your original code. The array of `buttonTFT` elements is private but there is public access to all the buttons almost as if the array was not private. In the case of your original code, one could write:
```c++
myButtonArray._buttons[0] = myButtonArray._buttons[1];
```
Now `_buttons[0]` *points to the same buttonTFT* as `_buttons[1]`.

Ouch. Now `myButtonArray._buttons[0]->read()` is literally the same thing as `myButtonArray._buttons[1]->read()`.

That said, my code does not make it a great deal better; the equivalent code:
```c++
myFourButtonArray[0] = myFourButtonArray[1];
```
Simply *copies* the right hand side over to the left hand side. You still have two distinct `buttonTFT` instances, with probably no memory leaks, but I am guessing that `buttonTFT` class may contain a reference to an Input pin, so the `_button[0]` pin will now be whatever `_button[1]` pin is because the member variable that stores the pin reference will be overwritten.

To solve this weakness, simply add the `const` qualifier to the beginning of the `operator[]` overload:
```c++
const buttonTFT &operator[](uint8_t index)
{ // };
```
Now the `buttonTFT` element cannot be altered. This of course brings in a new headache that all functions that rely on `myArray[n]` also need to be constant. It is up to you to determine how constant correctness should be interpreted and whether it is worth the hassle.

  [1]: http://www.cplusplus.com/doc/oldtutorial/templates/

body:
I want to share my final updated library (thanks to answers by Majenko&Charlie), perhaps it'll help others.

`.h` file

    template <uint8_t N>
    class buttonArray_TFT
    {
    public:
      int8_t dx = 5;         /* define spacing between buttons */
      int8_t dy = 5;         /* define spacing between buttons */
      uint8_t scale_f = 100; /* change the cale of array. 100% take entire screen */
      uint8_t shift_y = 255; /* Shifts in y director*/
      uint8_t shift_x = 255; /* Shifts in x director*/
      int shrink_shift = 0;  /* shrink array in pixels, and shifts up/ down (+/-) */

      uint8_t &a = butarray[0].a;
      uint8_t &b = butarray[0].b;
      uint8_t &txt_size = butarray[0].txt_size;
      uint16_t &txt_color = butarray[0].txt_color;
      uint16_t &border_color = butarray[0].border_color;
      uint16_t &face_color = butarray[0].face_color;
      bool &roundRect = butarray[0].roundRect;

    protected:
      ButtonTFT butarray[N];

    public:
      buttonArray_TFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
      void create_array(uint8_t R, uint8_t C, char *but_txt[]);
      uint8_t checkPress(TS_Point &p);
    };

and more in :
`.h` file :

    template <uint8_t N>
    buttonArray_TFT<N>::buttonArray_TFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft)
    {
      for (int i = 0; i < N; i++)
      {
        butarray[i].TS[0] = &ts;
        butarray[i].TFT[0] = &tft;
      }
    }

    template <uint8_t N>
    void buttonArray_TFT<N>::create_array(uint8_t R, uint8_t C, char *but_txt[])
    {
    \\ Code
    }

    template <uint8_t N>
    uint8_t buttonArray_TFT<N>::checkPress(TS_Point &p)
    {
      for (uint8_t i = 0; i < N; i++)
      {
        if (butarray[i].checkPress(p))
        {
          return i;
        }
      }
      return 99;
    }

body:
There are more options to solve your question.

----------

To use a template as recommended in the other answers is a fancy option, but if you use a template multiple times, it creates a real class for every template value and you will see it on used flash size.

----------

The best option in my opinion is to provide the array to the class over a constructor. Create a global array of buttons and hand it over to buttonArrayTFT object over a constructor.
```
const uint8_t BUTTON_COUNT = 12;
ButtonTFT buttons[BUTTON_COUNT];
ButtonArrayTFT buttonArrayTFT(buttons, BUTTON_COUNT);
```
The ButtonArrayTFT class (simplified) would be like:
```
class ButtonArrayTFT {
private:
  ButtonTFT *buttons;
  uint8_t count;
public:
  ButtonArrayTFT(ButtonTFT *_buttons, uint8_t _count) {
    buttons = _buttons;
    count = _count;
  }
```
----------

Other option is to use dynamic allocation on heap. If you would create a ButtonArrayTFT object only once at start and never delete it it would not cause heap fragmentation.
```
class ButtonArrayTFT {
private:
  ButtonTFT *buttons;
  uint8_t count;
public:
  ButtonArrayTFT(uint8_t _count) {
    count = _count;
    buttons = new ButtonTFT[count];
  }
```


body:
I have 3 motor drivers and all 3 other them only seem to only work on one of the 2 sides. I have used a voltmeter to check the voltages across the each of the 2 sections on each motor driver. For all 3 of the motor drivers, 2 of them had one side which had a voltage of 5V (which should be 7.2 volts as thats the power supply) and the other sides of the 2 motor drivers was 0-0.05V (so effectively no voltage). The other motor driver had no voltage from either of the 2 sides. Are all 3 of the motor drivers faulty or have I broke them? The schematic for the motor drivers was as follows:
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/fQWms.png

(Apart from instead of a 12V source, a 7.2V source is used buts thats the amount of Volts I need for the motors. The arduino I used was an Arduino mega rather than an UNO shown in this diagram as I got this diagram off the internet)
Heres a link for the place where I ordered the motor drivers from:
https://thepihut.com/products/l298n-motor-stepper-driver

Here is my code:
```cpp
    #include <PS2X_lib.h> //for v1.6
    int enA = 3;
    int in1 = 8;
    int in2 = 7;
    int enB = 9;
    int in3 = 5;
    int in4 = 4;
    int error = 0;
    byte type = 0;
    byte vibrate = 0;
    int light_one_pin = 36;
    int light_two_pin = 38;
    bool lights_on = false;
    PS2X ps2x;
    void setup(){
     Serial.begin(9600);
     pinMode(enA, OUTPUT);
     pinMode(in1, OUTPUT);
     pinMode(in2, OUTPUT);
     pinMode(in3, OUTPUT);
     pinMode(in4, OUTPUT);
     pinMode(light_one_pin, OUTPUT);
     pinMode(light_two_pin, OUTPUT);

     //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
     for(int x = 0; x < 100; x++)
     {
      error = ps2x.config_gamepad(13,11,10,12, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
     }
     error = 0;

    }

    void loop() {
      ps2x.read_gamepad(false, vibrate);

      if(ps2x.ButtonPressed(PSB_GREEN) && lights_on == false)
      {
         digitalWrite(light_one_pin, HIGH);
         digitalWrite(light_two_pin, HIGH);
         lights_on = true;
         Serial.println("on");
      }
      else if(ps2x.ButtonPressed(PSB_GREEN) && lights_on == true)
      {
          digitalWrite(light_one_pin, LOW);
          digitalWrite(light_two_pin, LOW);
          lights_on = false;
          Serial.println("off");
      }

      if(ps2x.Analog(PSS_LY) < 128)
        {
          digitalWrite(in1, LOW);//all fowards wheel
          digitalWrite(in2, HIGH);
          digitalWrite(in3, HIGH);
          digitalWrite(in4, LOW);
          analogWrite(enA, 255);
          analogWrite(enB, 255);
          Serial.println("forwards");

        }

        else if(ps2x.Analog(PSS_LY) > 128)
        {
          digitalWrite(in1, HIGH);//all backwards wheels
          digitalWrite(in2, LOW);
          digitalWrite(in3, LOW);
          digitalWrite(in4, HIGH);
          analogWrite(enA, 255);
          analogWrite(enB, 255);
          Serial.println("backwards");

        }

        else if(ps2x.Analog(PSS_LY) == 128)
        {
          analogWrite(enA, 0);
          analogWrite(enB, 0);
          Serial.println("stationary");

        }

        else if(ps2x.Analog(PSS_LX) == 128)
        {
            //Serial.println("still");
            //wheel_steering_servo.write(wheel_steering_servo_angle);
        }

        Serial.println(ps2x.Analog(PSS_LX));

    }
```

title: motor driver only works on one side:

Answers: 2

body:
There are a couple of things that you can check-

**Your code**-

Chances are that all of the motor drivers are functional (as manufacturing defects are very rare) and that there is something wrong with the code.

**1-** **The motor driver that you are using has 2 pins that should be labeled "ENA", "ENB" (or some variant of these), in order for the motor driver to work on both sides, both these pins must be high, if any one of these are low, then that side will not work. I highly recommend that you directly connect these 2 pins to 5V, and use the 4 inputs for the control.**

**2-** The 4 input pins labeled "IN1", "IN2", "IN3", "IN4" are the pins that instructs the driver to move each side forward or back, check your code to make sure that these pins are high or low as per your requirement.

Another thing is that both the forward and back inputs of one side must not be high at the same time otherwise it won't work

**Your hardware**-

If you find that something is getting abnormally hot on the boards or worse if something is burnt, then you should check your circuit and make sure there are no problems.

--
A problem in your code, is that "ENB" is not set as an output and hence is not high, you should also modify the setup to set the "ENA", "ENB" to high to make sure that it is on.

So your setup should go something like this-

```c++
     Serial.begin(9600);
     pinMode(enA, OUTPUT);
     pinMode(enB, OUTPUT);
     digitalWrite(enA, HIGH);
     digitalWrite(enB, HIGH);
     pinMode(in1, OUTPUT);
     pinMode(in2, OUTPUT);
     pinMode(in3, OUTPUT);
     pinMode(in4, OUTPUT);
     pinMode(light_one_pin, OUTPUT);
     pinMode(light_two_pin, OUTPUT);
```

body:
Just a correction to something Coder9390 wrote:

The ENA and ENB pins on this motor drive are not supposed to be used as digital pins and receive HIGH or LOW, but as analog pins and receive a value in range 0-255 using a PWM pin (PWM pins are marked on the board with a ~). This enables you to control the speed of the motor, by simulating low voltage.

In your code you actually seem to do this correctly, so I don't think this is the problem. Setting the pinMode of ENA and ENB to OUTPUT on the other hand is correct, so it might actually be the problem. I couldn't reproduce your bug this way though, so it might be something else.

In case you don't need to control the speed of the motor and want it to always go full speed, you can use jumpers to short each EN pin with it's orthogonal-adjacent pin (which are marked in your image as 5v) to achieve the same effect of connecting them to 5v "manually" as Coder9390 suggested (basically by placing the jumpers there you are doing exactly that - connecting the EN pins to 5v).

Coder9390, if you implicitly meant to suggest using jumpers like this, then sorry for misrepresenting your answer. I thought it wasn't clear to beginners who might get here, and that it requires an elaboration.

See this motor driver usage explained here: [https://create.arduino.cc/projecthub/ryanchan/how-to-use-the-l298n-motor-driver-b124c5][1]

  [1]: https://create.arduino.cc/projecthub/ryanchan/how-to-use-the-l298n-motor-driver-b124c5


body:
I understand [how pullup and pulldown resistors work][1] with push buttons and I also understand that an analogous idea can be applied to slide switches. Furthermore, I know that some versions of [Arduino have an internal pullup resistor][2] that can be used, if you adjust the code properly.

I was wondering, if I can, without using the internal pullup resistor, wire a slide switch without any kind of resistor like so:

[![enter image description here][3]][3]

As I understand, this should behave exactly the same as using a pull-down resistor. If the switch is on the left side, pin 7 would read `LOW` and if the switch is on the right side, it would read `HIGH`.

Is that a problem with wiring the switch like this? Is there a reason why using a resistor would be better?

In my final project I intend to use a Digispark board and I would not like to rely on its internal resistor and I also would like to avoid using an external resistor if I can.

  [1]: https://www.youtube.com/watch?v=uWrN1RCQrgA&list=PLsCUTjzpUHK8X3pCU6nS0AFADk0Fw7MhM
  [2]: https://www.arduino.cc/en/Tutorial/Foundations/DigitalPins
  [3]: https://i.stack.imgur.com/DtaX1.png

title: Is it possible to use a slide switch without a resistor?

Answers: 1

body:
You *may* be able to do it, or you may not. It depends on the switch.

There are two classes of slide switch:

* Make-before-break
* Break-before-make

In the former the contact you are sliding to is connected *before* the one you are sliding away from is disconnected. This can cause untold problems as you will basically create a short circuit between 5V and GND. Everything will die.

In the latter the contact you are sliding away from is disconnected first, and then the new contact you are sliding towards is connected. That is safer, but it does mean that there is a short period while you're sliding the switch where neither contact is connected. At this time the input pin is floating - just as if you had nothing connected at all (which is in fact the case).

That is of course not a desirable scenario as it's probably the most amount of bounce you will ever see in a switch - bounce you need to eliminate in software to give you a clean signal.

That period of uncertainty is eliminated if you have a pullup or pulldown resistor, since there is never a period where there is no connection, and there's never a period where you risk shorting out power and ground. All you have to content with then is the natural bounce of the contacts as they close.


body:
I've written a sketch to drive a differential drive system, specifically - to be able to drive strait. This does work.

So I am trying to add the ability to stop when the path is blocked using US sensor directed towards the front of the "car". I manage to get correct readings, but my "car" cannot move strait anymore.

I tried using the ping_timer() functionality of NewPing library, but it did not solve the problem. When the ultrasonic code is commented out, my "car" can go strait.

My algorithm for strait driving is essentially to compare the pulses from two rotary encoders fitted to the wheels, and if one exceeds the other by more than one pulse, shut down the relevant motor and turn on the other motor (if it wasn't on already) so the slower motor has a chance to keep-up.

I wonder if there is a problem in my code that I cannot find, I will be very thankful for anyone who can review my sketch:

    #include <Arduino.h>
    // #include <Servo.h>
    #include <TimedAction.h>
    #include <NewPing.h>

    #define RIGHT_MOTOR_ON (0 - int(pulseCountRight <= pulseCountLeft + 1))
    #define LEFT_MOTOR_ON (0 - int(pulseCountLeft <= pulseCountRight + 1))

    const int EN_RIGHT = 6;
    const int IN1_RIGHT = 7;
    const int IN2_RIGHT = 8;
    const int ENCODER_RIGHT = 2;

    const int EN_LEFT = 5;
    const int IN1_LEFT = 10;
    const int IN2_LEFT = 11;
    const int ENCODER_LEFT = 3;

    const int SPEED = 100;

    const int BW_TRUE = -1;
    const int BW_FALSE = 0;

    // const int SERVO_PIN = 9;
    // const int SERVO_MAX_RIGHT = 0;
    // const int SERVO_MAX_LEFT = 125;
    const int SERVO_SWEEP_DELAY = 150;
    // const int SERVO_TURN_RIGHT = -25;
    // const int SERVO_TURN_LEFT = 25;

    const int ULTRASONIC_TOO_CLOSE = 20;
    // Timeout is the maximum time it would take sound to do a roundtrip with length of "ULTRASONIC_TOO_CLOSE".
    // Formula is: DIST(cm) x TIME(us per cm).
    const int ULTRASONIC_TIMEOUT = ULTRASONIC_TOO_CLOSE * US_ROUNDTRIP_CM;
    const int ULTRASONIC_TRIG_PIN = 13;
    const int ULTRASONIC_ECHO_PIN = 12;

    unsigned int pulseCountRight = 0;
    unsigned int pulseCountLeft = 0;

    int movingStrait = BW_TRUE;
    int stopping = BW_TRUE;

    double distance = 0.0;

    void pingTimer();
    void checkTimer();

    NewPing sonar(ULTRASONIC_TRIG_PIN, ULTRASONIC_ECHO_PIN, 400);

    TimedAction pingTimerAction(SERVO_SWEEP_DELAY, pingTimer);

    // Servo myServo;

    void countPulse(unsigned int &counter) {
      ++counter;

      char c[1000];
      sprintf(c, "Pulses (right,left): %d,%d, Motor on (right,left): %d,%d", pulseCountRight, pulseCountLeft, RIGHT_MOTOR_ON, LEFT_MOTOR_ON);
      Serial.println(c);

      analogWrite(EN_RIGHT, SPEED & (RIGHT_MOTOR_ON | ~movingStrait) & ~stopping);
      analogWrite(EN_LEFT, SPEED & (LEFT_MOTOR_ON | ~movingStrait) & ~stopping);
    }

    void forward() {
      movingStrait = BW_TRUE;
      stopping = BW_FALSE;
      pulseCountRight = 0;
      pulseCountLeft = 0;

      digitalWrite(IN1_RIGHT, LOW);
      digitalWrite(IN2_RIGHT, HIGH);

      digitalWrite(IN1_LEFT, LOW);
      digitalWrite(IN2_LEFT, HIGH);

      analogWrite(EN_RIGHT, SPEED);
      analogWrite(EN_LEFT, SPEED);
    }

    void backwards() {
      movingStrait = BW_TRUE;
      stopping = BW_FALSE;
      pulseCountRight = 0;
      pulseCountLeft = 0;

      digitalWrite(IN1_RIGHT, HIGH);
      digitalWrite(IN2_RIGHT, LOW);

      digitalWrite(IN1_LEFT, HIGH);
      digitalWrite(IN2_LEFT, LOW);

      analogWrite(EN_RIGHT, SPEED);
      analogWrite(EN_LEFT, SPEED);
    }

    void right() {
      movingStrait = BW_FALSE;
      stopping = BW_FALSE;

      digitalWrite(IN1_RIGHT, LOW);
      digitalWrite(IN2_RIGHT, HIGH);

      digitalWrite(IN1_LEFT, HIGH);
      digitalWrite(IN2_LEFT, LOW);

      analogWrite(EN_RIGHT, SPEED);
      analogWrite(EN_LEFT, SPEED);
    }

    void left() {
      movingStrait = BW_FALSE;
      stopping = BW_FALSE;

      digitalWrite(IN1_RIGHT, HIGH);
      digitalWrite(IN2_RIGHT, LOW);

      digitalWrite(IN1_LEFT, LOW);
      digitalWrite(IN2_LEFT, HIGH);

      analogWrite(EN_RIGHT, SPEED);
      analogWrite(EN_LEFT, SPEED);
    }

    void stop() {
      movingStrait = BW_FALSE;
      stopping = BW_TRUE;

      digitalWrite(IN1_RIGHT, LOW);
      digitalWrite(IN2_RIGHT, LOW);

      digitalWrite(IN1_LEFT, LOW);
      digitalWrite(IN2_LEFT, LOW);
    }

    void setup() {
      Serial.begin(9600);
      Serial.println("DifferentialDrive2");

      pinMode(EN_RIGHT, OUTPUT);
      pinMode(EN_LEFT, OUTPUT);
      pinMode(IN1_RIGHT, OUTPUT);
      pinMode(IN2_RIGHT, OUTPUT);
      pinMode(IN1_LEFT, OUTPUT);
      pinMode(IN2_LEFT, OUTPUT);

      pinMode(ENCODER_RIGHT, INPUT_PULLUP);
      pinMode(ENCODER_LEFT, INPUT_PULLUP);

      // pinMode(SERVO_PIN, OUTPUT);

      pinMode(ULTRASONIC_TRIG_PIN, OUTPUT);
      pinMode(ULTRASONIC_ECHO_PIN, INPUT);

      attachInterrupt(digitalPinToInterrupt(ENCODER_RIGHT), [] { countPulse(pulseCountRight); }, CHANGE);
      attachInterrupt(digitalPinToInterrupt(ENCODER_LEFT), [] { countPulse(pulseCountLeft); }, CHANGE);

      digitalWrite(IN1_RIGHT, LOW);
      digitalWrite(IN2_RIGHT, HIGH);

      digitalWrite(IN1_LEFT, LOW);
      digitalWrite(IN2_LEFT, HIGH);

      analogWrite(EN_RIGHT, SPEED);
      analogWrite(EN_LEFT, SPEED);

      // myServo.attach(SERVO_PIN);
      // myServo.write((SERVO_MAX_RIGHT + SERVO_MAX_LEFT) / 2);

      forward();
    }

    unsigned long start_time = 0;

    void pingTimer() {
      sonar.timer_stop();
      start_time = micros();
      sonar.ping_timer(checkTimer);
      // NewPing::timer_us(ULTRASONIC_TIMEOUT * 4, checkTimer);
    }

    void checkTimer() {
      // static int angle = SERVO_MAX_RIGHT;
      // static int direction = SERVO_TURN_LEFT;
      if (micros() - ULTRASONIC_TIMEOUT >= start_time && sonar.check_timer()) {
        distance = ((float) sonar.ping_result / (float) US_ROUNDTRIP_CM) / 2.0;
        if (distance < ULTRASONIC_TOO_CLOSE) {
          stop();
          Serial.println("stoppeing");
        }
      }
      // sonar.timer_stop();
    }

    void loop() {
      pingTimerAction.check();
      if (distance == 0 || distance > ULTRASONIC_TOO_CLOSE) {
        // forward();
      }
    }

Here is a printout of the pulse counts and the status of the motors for a run:

    DifferentialDrive2
    Pulses (right,left): 1,0, Motor on (right,left): -1,-1
    Pulses (right,left): 1,1, Motor on (right,left): -1,-1
    Pulses (right,left): 2,1, Motor on (right,left): -1,-1
    Pulses (right,left): 3,1, Motor on (right,left): 0,-1
    Pulses (right,left): 4,1, Motor on (right,left): 0,-1
    Pulses (right,left): 5,1, Motor on (right,left): 0,-1
    Pulses (right,left): 6,1, Motor on (right,left): 0,-1
    Pulses (right,left): 7,1, Motor on (right,left): 0,-1
    Pulses (right,left): 8,1, Motor on (right,left): 0,-1
    Pulses (right,left): 9,1, Motor on (right,left): 0,-1
    Pulses (right,left): 9,2, Motor on (right,left): 0,-1
    Pulses (right,left): 9,3, Motor on (right,left): 0,-1
    Pulses (right,left): 9,4, Motor on (right,left): 0,-1
    Pulses (right,left): 9,5, Motor on (right,left): 0,-1

    Pulses (right,left): 9,6, Motor on (right,left): 0,-1
    Pulses (right,left): 9,7, Motor on (right,left): 0,-1
    Pulses (right,left): 9,8, Motor on (right,left): -1,-1
    Pulses (right,left): 9,9, Motor on (right,left): -1,-1
    Pulses (right,left): 10,9, Motor on (right,left): -1,-1
    Pulses (right,left): 11,9, Motor on (right,left): 0,-1
    Pulses (right,left): 12,9, Motor on (right,left): 0,-1
    Pulses (right,left): 13,9, Motor on (right,left): 0,-1
    Pulses (right,left): 14,9, Motor on (right,left): 0,-1
    Pulses (right,left): 15,9, Motor on (right,left): 0,-1
    Pulses (right,left): 16,9, Motor on (right,left): 0,-1
    Pulses (right,left): 17,9, Motor on (right,left): 0,-1
    Pulses (right,left): 17,10, Motor on (right,left): 0,-1
    Pulses (right,left): 17,11, Motor on (right,left): 0,-1
    Pulses (right,left): 17,12, Motor on (right,left): 0,-1
    Pulses (right,left): 17,13, Motor on (right,left): 0,-1
    Pulses (right,left): 17,14, Motor on (right,left): 0,-1
    Pulses (right,left): 17,15, Motor on (right,left): 0,-1
    Pulses (right,left): 17,16, Motor on (right,left): -1,-1
    Pulses (right,left): 17,17, Motor on (right,left): -1,-1
    Pulses (right,left): 18,17, Motor on (right,left): -1,-1
    Pulses (right,left): 19,17, Motor on (right,left): 0,-1
    Pulses (right,left): 20,17, Motor on (right,left): 0,-1
    Pulses (right,left): 21,17, Motor on (right,left): 0,-1
    Pulses (right,left): 22,17, Motor on (right,left): 0,-1
    Pulses (right,left): 23,17, Motor on (right,left): 0,-1
    Pulses (right,left): 24,17, Motor on (right,left): 0,-1
    Pulses (right,left): 24,18, Motor on (right,left): 0,-1
    Pulses (right,left): 24,19, Motor on (right,left): 0,-1
    Pulses (right,left): 24,20, Motor on (right,left): 0,-1

What bugs me about this output is that I am expecting the slower motor not to open such large gaps, and I also know that in reality it did not open such large gaps. I suspect some pulses don't get counted for some reason, perhaps I am putting too much work on the micro-controller.

If the problem is not in my code, I wonder if this problem can be solved on a single Arduino device and I just have a weak algorithm, or perhaps it requires a separate device for the ultrasonic and a separate device for the differential drive.

Thanks in advance for any helpers.

PS. I am using this motor shield: [https://osoyoo.com/2020/08/06/osoyoo-motor-shield/][1]

  [1]: https://osoyoo.com/2020/08/06/osoyoo-motor-shield/

title: can differential drive work together with ultrasonic sensor?

Answers: 1

body:
Thanks to @chrisl, here is the answer:

The NewPing library uses Timer2 on UNO, which means pin 3 (and 11) is not available for use. I have been using pin 3 for interrupts from a rotary encoder, which is probably the reason for the sluggish performance.

The bad news are there are only two interrupt pins on UNO - 2 and 3, so if I want to attach two rotary encoders to my two drive wheels, I cannot use interrupts to count the pulses. There may be a workaround, I couldn't think of one, but I think IR proximity sensors may be a better choice than my ultrasonic sensor because judging from code examples they are neither blocking nor do they need timers, but I didn't really dive deep into them yet so I may be wrong on this.