# Question
Title: To control the relay switching in nextion using esp32 Microcontroller
I have developed the code to control the relay switching on/off using nextion display and esp32. But whenever I press my dual state button in the nextion display there is some delay and I need to press my dual state button continuously in nextion display for about 10 to 15 seconds to switch on/off the relay.

I am stuck in this work and I 'm looking for help. I need to switch on/off the relay on a single tap on the dual sate button on nextion display. Below I have attached my code,

```
#include "NexDualStateButton.h"
#include "Nextion.h"
#include "DHT.h"

#define DHTPIN 27
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
int R1 = 2;
uint32_t dual_state ;

NexText tTempC = NexText(0, 4, "tTempC");
NexText tHumidity = NexText(0, 6, "tHumidity");
NexDSButton bt0 = NexDSButton(0, 8, "bt0");

char buffer[100] = {0};

NexTouch *nex_listen_list[] =
{
    &bt0,
    NULL
};

void bt0PopCallback(void *ptr)
{
  uint32_t dual_state;
  NexDSButton *btn = (NexDSButton *)ptr;

  dbSerialPrintln("bt0PopCallback");
  dbSerialPrint("ptr=");

  dbSerialPrintln((uint32_t)ptr);
  memset(buffer, 0, sizeof(buffer));

  bt0.getValue(&dual_state);

  if(dual_state>0)
  {
    digitalWrite(R1, LOW);
  }
  else
  {
    digitalWrite(R1, HIGH);
  }
}

void setup(void) {
   dht.begin();
   Serial.begin(9600);
   pinMode(R1, OUTPUT);

   nexInit();
   bt0.attachPop(bt0PopCallback, &bt0);

   Serial.println("DHT Sensor Reading");
   dbSerialPrintln("setup done");
}

void loop(void) {
  nexLoop(nex_listen_list);
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  if (isnan(h) || isnan(t)) {
    Serial2.println(F("Failed to read from DHT sensor!"));
    return;
  }

  static char temperatureCTemp[10];
  dtostrf(t, 6, 2, temperatureCTemp);
  tTempC.setText(temperatureCTemp);

  char hTemp[10] = {0};
  utoa(int(h), hTemp, 10);
  tHumidity.setText(hTemp);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print("°C ");
  //Serial2.print(F("tTempC.txt="));

  //Serial.print("");
  //Serial.print(F("tHumidity.txt:\ "));
  //Serial.print(h);
  //Serial.write(0xff);
  //Serial.write(0xff);
  //Serial.write(0xff);
}

```

Thanks in Advance.

# Answer
> 1 votes
I think this method inefficent. Because ESP32 continuously listens to the button state.

You will try this method . Working for me .

```
int R1 = 2;
NexDSButton bt0 = NexDSButton(0, 8, "bt0");
uint32_t dual_state=0;

void setup(){
nexInit();
pinMode(R1, OUTPUT);
}
void loop(){
bt0.getValue(&dual_state);

if(dual_state==1) //When pressed dual state button dual_state =1
  {
    digitalWrite(R1, HIGH);
  }
  else if(dual_state==0)
  {
    digitalWrite(R1,LOW );
  }

}

```

# Answer
> 0 votes
This is my updated code to display the temperature and humidity in Nextion display and also to control the relay switching in Nextion display. It works good.

```
#include "NexDualStateButton.h"
#include "Nextion.h"
#include "DHT.h"

#define DHTPIN 27
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

int R1 = 2;
NexDSButton bt0 = NexDSButton(0, 8, "bt0");
NexText tTempC = NexText(0, 4, "tTempC");
NexText tHumidity = NexText(0, 6, "tHumidity");
uint32_t dual_state=0;

void setup(){
  dht.begin();
  nexInit();
  pinMode(R1, OUTPUT);
}

void loop(){
  bt0.getValue(&dual_state);

  if(dual_state==1) //When pressed dual state button dual_state =1
  {
    digitalWrite(R1, HIGH);
  }
  else if(dual_state==0)
  {
    digitalWrite(R1,LOW );
  }
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  if (isnan(h) || isnan(t)) {
    Serial2.println(F("Failed to read from DHT sensor!"));
    return;
  }

  static char temperatureCTemp[10];
  dtostrf(t, 6, 2, temperatureCTemp);
  tTempC.setText(temperatureCTemp);

  char hTemp[10] = {0};
  utoa(int(h), hTemp, 10);
  tHumidity.setText(hTemp);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print("°C ");

}

```

# Answer
> 0 votes
There is a simpler way to print the temperature to the display and call the BT button without using the Nextion Library. In this example, I am using a TCA9548A because I am using 2 BMP280s.

```
void TEMP() {
  delay(125);
  TCA9548A(0);
  HMISerial10.print("t8.txt=\"");
  HMISerial10.print((bmp.readTemperature() * 1.8) + 32);
  HMISerial10.print("\"");
  HMISerial10.write(0xff);
  HMISerial10.write(0xff);
  HMISerial10.write(0xff);
  Serial.print("Inside Temp: ");
  Serial.println((bmp.readTemperature() * 1.8) + 32);

  TCA9548A(1);
  HMISerial10.print("t7.txt=\"");
  HMISerial10.print((bmp.readTemperature() * 1.8) + 32);
  HMISerial10.print("\"");
  HMISerial10.write(0xff);
  HMISerial10.write(0xff);
  HMISerial10.write(0xff);
  Serial.print("Outside Temp: ");
  Serial.println((bmp.readTemperature() * 1.8) + 32);
}

```

Here I have it looking for a button from the Nextion

```
void dfd_listen() {

  delay(30);
  dfd = ""; //dfd means Data From Display
  while (HMISerial5.available()) { //This will look to see if there is something coming from the Nextion
    dfd += char(HMISerial5.read());
  }

  if (dfd.substring(1, 4) == "bt4" && dfd.substring(0, 1) == "0") {
    digitalWrite(R6, LOW);   // Roof Lights
    HMISerial5.write(0xff);  // We always have to send this three lines after each command sent to the nextion display.
    HMISerial5.write(0xff);
    HMISerial5.write(0xff);
    Serial.println("Roof Lights OFF");
  } else if (dfd.substring(1, 4) == "bt4" && dfd.substring(0, 1) == "1") {
    digitalWrite(R6, LOW);   // Roof Lights
    HMISerial5.write(0xff);  // We always have to send this three lines after each command sent to the nextion display.
    HMISerial5.write(0xff);
    HMISerial5.write(0xff);
    Serial.println("Roof Lights ON");
  }

  if (dfd.substring(1, 4) == "b17") {
    HMISerial5.print("page 1");
    HMISerial5.write(0xff);  // We always have to send this three lines after each command sent to the nextion display.
    HMISerial5.write(0xff);
    HMISerial5.write(0xff);
    Serial.println("Change to Page 1");
    dfd = "";
    delay(100);
  }

```

Now this shows both BT and B buttons. The HMISerial are my serial ports the Nextion are attached to. The "dfd" is set as a string before your setup. For the Nextion button, you just have to add a value and set it as a string, in this case, my value is va11. Then on the button on the press event, you would put something like this.

```
  if(bt4.val==1)
{
  cov bt4.val,va11.txt,1
  va11.txt+="bt4"
  print va11.txt
  t4.pco=17576
}else if(bt4.val==0)
{
  cov bt4.val,va11.txt,1
  va11.txt+="bt4"
  print va11.txt
  t4.pco=57033
}

```

---
Tags: arduino-ide, esp32, relay, dht22
---


title: Processing doesn't respond to arduino

text:
# Question
Title: Processing doesn't respond to arduino
First of all if I make a wrong sentence this is because my main language isn't english. I have a homework so i am trying to make a radar with Arduino IDE and Processing. I found and wrote the codes from internet but processing does not respond to ultrasonic sensor and i tought maybe it isn't detecting the serial port. Code from Processing:

```
import processing.serial.*; // imports library for serial communication
import java.awt.event.KeyEvent; // imports library for reading the data from the serial port
import java.io.IOException;

Serial myPort; // defines Object Serial
// defubes variables
String angle="";
String distance="";
String data="";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1=0;
int index2=0;
PFont orcFont;

void setup() {

 size (1600, 900); // ***CHANGE THIS TO YOUR SCREEN RESOLUTION***
 smooth();
 myPort = new Serial(this,"COM3", 9600); // starts the serial communication
 myPort.bufferUntil('.'); // reads the data from the serial port up to the character '.'. So actually it reads this: angle,distance.
 orcFont = loadFont("Calibri-Bold-48.vlw");
}

void draw() {

  fill(98,245,31);
  textFont(orcFont);
  // simulating motion blur and slow fade of the moving line
  noStroke();
  fill(0,4);
  rect(0, 0, width, height-height*0.065);

  fill(98,245,31); // green color
  // calls the functions for drawing the radar
  drawRadar();
  drawLine();
  drawObject();
  drawText();
}

void serialEvent (Serial myPort) { // starts reading data from the Serial Port
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('.');
  data = data.substring(0,data.length()-1);

  index1 = data.indexOf(","); // find the character ',' and puts it into the variable "index1"
  angle= data.substring(0, index1); // read the data from position "0" to position of the variable index1 or thats the value of the angle the Arduino Board sent into the Serial Port
  distance= data.substring(index1+1, data.length()); // read the data from position "index1" to the end of the data pr thats the value of the distance

  // converts the String variables into Integer
  iAngle = parseInt(angle);
  iDistance = parseInt(distance);
}

void drawRadar() {
  pushMatrix();
  translate(width/2,height-height*0.074); // moves the starting coordinats to new location
  noFill();
  strokeWeight(2);
  stroke(98,245,31);
  // draws the arc lines
  arc(0,0,(width-width*0.0625),(width-width*0.0625),PI,TWO_PI);
  arc(0,0,(width-width*0.27),(width-width*0.27),PI,TWO_PI);
  arc(0,0,(width-width*0.479),(width-width*0.479),PI,TWO_PI);
  arc(0,0,(width-width*0.687),(width-width*0.687),PI,TWO_PI);
  // draws the angle lines
  line(-width/2,0,width/2,0);
  line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30)));
  line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60)));
  line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90)));
  line(0,0,(-width/2)*cos(radians(120)),(-width/2)*sin(radians(120)));
  line(0,0,(-width/2)*cos(radians(150)),(-width/2)*sin(radians(150)));
  line((-width/2)*cos(radians(30)),0,width/2,0);
  popMatrix();
}

void drawObject() {
  pushMatrix();
  translate(width/2,height-height*0.074); // moves the starting coordinats to new location
  strokeWeight(9);
  stroke(255,10,10); // red color
  pixsDistance = iDistance*((height-height*0.1666)*0.025); // covers the distance from the sensor from cm to pixels
  // limiting the range to 40 cms
  if(iDistance<40){
    // draws the object according to the angle and the distance
  line(pixsDistance*cos(radians(iAngle)),-pixsDistance*sin(radians(iAngle)),(width-width*0.505)*cos(radians(iAngle)),-(width-width*0.505)*sin(radians(iAngle)));
  }
  popMatrix();
}

void drawLine() {
  pushMatrix();
  strokeWeight(9);
  stroke(30,250,60);
  translate(width/2,height-height*0.074); // moves the starting coordinats to new location
  line(0,0,(height-height*0.12)*cos(radians(iAngle)),-(height-height*0.12)*sin(radians(iAngle))); // draws the line according to the angle
  popMatrix();
}

void drawText() { // draws the texts on the screen

  pushMatrix();
  if(iDistance>40) {
  noObject = "Out of Range";
  }
  else {
  noObject = "In Range";
  }
  fill(0,0,0);
  noStroke();
  rect(0, height-height*0.0648, width, height);
  fill(98,245,31);
  textSize(25);

  text("10cm",width-width*0.3854,height-height*0.0833);
  text("20cm",width-width*0.281,height-height*0.0833);
  text("30cm",width-width*0.177,height-height*0.0833);
  text("40cm",width-width*0.0729,height-height*0.0833);
  textSize(40);
  text("Obje: " + noObject, width-width*0.875, height-height*0.0277);
  text("Açı: " + iAngle +" °", width-width*0.48, height-height*0.0277);
  text("Mesafe: ", width-width*0.26, height-height*0.0277);
  if(iDistance<40) {
  text("        " + iDistance +" cm", width-width*0.225, height-height*0.0277);
  }
  textSize(25);
  fill(98,245,60);
  translate((width-width*0.4994)+width/2*cos(radians(30)),(height-height*0.0907)-width/2*sin(radians(30)));
  rotate(-radians(-60));
  text("30°",0,0);
  resetMatrix();
  translate((width-width*0.503)+width/2*cos(radians(60)),(height-height*0.0888)-width/2*sin(radians(60)));
  rotate(-radians(-30));
  text("60°",0,0);
  resetMatrix();
  translate((width-width*0.507)+width/2*cos(radians(90)),(height-height*0.0833)-width/2*sin(radians(90)));
  rotate(radians(0));
  text("90°",0,0);
  resetMatrix();
  translate(width-width*0.513+width/2*cos(radians(120)),(height-height*0.07129)-width/2*sin(radians(120)));
  rotate(radians(-30));
  text("120°",0,0);
  resetMatrix();
  translate((width-width*0.5104)+width/2*cos(radians(150)),(height-height*0.0574)-width/2*sin(radians(150)));
  rotate(radians(-60));
  text("150°",0,0);
  popMatrix();
}

```

Code from Arduino IDE:

```
#include <Servo.h>   // servo motor kütüphanesi
#define trigPin 4    // ultrasonik sensör trig pini
#define echoPin 3    // ultrasonik sensör echo pini
Servo servoMotor;     // servo motor nesnesi
int angle = 0;        // servo motor açısı
long duration, distance;  // ultrasonik sensör mesafesi

void setup() {
  Serial.begin(9600);  // seri haberleşme hızı
  servoMotor.attach(9); // servo motor pin numarası
}

void loop() {
  for(angle = 0; angle < 180; angle += 10){  // servo motor açıları
    servoMotor.write(angle);  // servo motoru hareket ettir
    delay(200);               // bekleme süresi
    distance = getDistance(); // mesafe ölçümü
    Serial.print(angle);      // açıyı yazdır
    Serial.print(",");
    Serial.println(distance); // mesafeyi yazdır
  }
}

long getDistance(){ // ultrasonik sensör mesafe ölçümü
  pinMode(trigPin, OUTPUT);
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  distance = duration / 58.2;
  return distance;
}

```

Thank you for the help!

# Answer
Your processing code is looking for something that ends in a '.'

Your arduino code is sending angle,distnace\[new line\]

So either change your processing code to look for '\n' (the new line character) rather than '.' or change your arduino code to add a . to the end:

```
Serial.print(angle);      // açıyı yazdır
Serial.print(",");
Serial.print(distance); // mesafeyi yazdır
Serial.print(".");

```
> 1 votes

---
Tags: arduino-uno, signal-processing
---


# Question
Title: How to pass Encoder object to constructor of a different class
I am trying to create a class (Arm) that controls an arm. The arms have 2 motors, each with an encoder, so I pass 4 integers for the pins and I am trying to pass 2 pointers (one for each encoder object).

the .ino file is:

```
#include "Arm.h"
#include <Encoder.h>

//motor driver pins
#define ShoulderUP 7
#define ShoulderDW 8

#define ElbowUP 9
#define ElbowDW 10

#define encoderShoulderPinA 20
#define encoderShoulderPinB 21

#define encoderElbowPinA 22
#define encoderElbowPinB 23

//make encoder objects
Encoder ElbowEncoder(encoderElbowPinA, encoderElbowPinB);
Encoder ShoulderEncoder(encoderShoulderPinA, encoderShoulderPinB);

//make arm object
Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, ElbowEncoder, ShoulderEncoder);

void setup() {
  Serial.begin(9600);
}

void loop() {

  Arm1.ShoulderMoveTime(1, 255, 1000);
}

```

the .h file is:

```
#ifndef Arm_h
#define Arm_h

#include <Arduino.h>
#include <Encoder.h>

class Arm {

public:
  Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder);

  //pins connected to your encoder:
  //   Best Performance: both pins have interrupt capability
  //   Good Performance: only the first pin has interrupt capability
  //   Low Performance:  neither pin has interrupt capability

  void ShoulderMoveTime(int dir, int speed, int time);
  //dir = 0 means up, dir = 1 means down; speed between 0-255
  void ElbowMoveTime(int dir, int speed, int time);
  //dir = 0 means up, dir = 1 means down; speed between 0-255

  //Moves arm to poition given
  void ArmMovePosition(int shoulderPos, int elbowPos);

  // calibrates current arm position to zero
  void ZeroArm();

  //returns position of the arm
  void getArmPosition();

private:
  Encoder *ElbowEncoder;
  Encoder *ShoulderEncoder;
  int _ShoulderUpPin;
  int _ShoulderDownPin;
  int _ElbowUpPin;
  int _ElbowDownPin;
};

#endif

```

and the .cpp file is:

```
#include "Arduino.h"
#include "Encoder.h"
#include "Arm.h"

Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder) {

  pinMode(ShoulderUpPin, OUTPUT);
  pinMode(ShoulderDownPin, OUTPUT);
  pinMode(ElbowUpPin, OUTPUT);
  pinMode(ElbowDownPin, OUTPUT);

  _ShoulderUpPin = ShoulderUpPin;
  _ShoulderDownPin = ShoulderDownPin;
  _ElbowUpPin = ElbowUpPin;
  _ElbowDownPin = ElbowDownPin;
  //_ShoulderEncoderPinA = ShoulderEncoderPinA;
  //_ShoulderEncoderPinB = ShoulderEncoderPinB;
  //_ElbowEncoderPinA = ElbowEncoderPinA;
 // _ElbowEncoderPinB = ElbowEncoderPinB;
  ElbowEncoder = *ElbowEncoder;
  ShoulderEncoder = *ShoulderEncoder;
  //ElbowEncoder(_ElbowEncoderPinA, _ElbowEncoderPinB);
  //ShoulderEncoder(_ShoulderEncoderPinA, _ShoulderEncoderPinB);
}

void Arm::ShoulderMoveTime(int dir, int speed, int time) {
...
}

void Arm::ElbowMoveTime(int dir, int speed, int time) {
 ...
}

void Arm::ArmMovePosition(int shoulderPos, int elbowPos) {
  int ShoulderinitialPos = ShoulderEncoder.read();
  int ElbowinitialPos = ElbowEncoder.read();

  //TODO:I think this will only move one joint at a time

  //Move shoulder-------------------------------------------------------------------------------------
  if (shoulderPos > ShoulderinitialPos) {  //check to see which direction arm needs to move

    while (shoulderPos > ShoulderEncoder.read()) {  //while the target position is greater than the motor's actual position, move the shoulder up
      digitalWrite(_ShoulderUpPin, HIGH);           //THIS MAY BE REVERSED
    }
    digitalWrite(_ShoulderUpPin, LOW);  //stop the arm from moving up

  } else if (shoulderPos < ShoulderinitialPos) {

    while (shoulderPos < ShoulderEncoder.read()) {
      digitalWrite(_ShoulderDownPin, HIGH);
    }
    digitalWrite(_ShoulderDownPin, LOW);

  } else {
    Serial.print("Error: invalid shoulder target position");
  }

  //Move elbow-------------------------------------------------------------------------------------
  if (elbowPos > ElbowinitialPos) {  //check to see which direction arm needs to move

    while (elbowPos > ElbowEncoder.read()) {  //while the target position is greater than the motor's actual position, move the elbow up
      digitalWrite(_ElbowUpPin, HIGH);        //THIS MAY BE REVERSED
    }
    digitalWrite(_ElbowUpPin, LOW);  //stop the arm from moving up

  } else if (elbowPos < ElbowinitialPos) {

    while (elbowPos < ElbowEncoder.read()) {
      digitalWrite(_ElbowDownPin, HIGH);
    }
    digitalWrite(_ElbowDownPin, LOW);

  } else {
    Serial.print("Error: invalid elbow target position");
  }
}

void Arm::ZeroArm() {
  ShoulderEncoder.write(0);
  ElbowEncoder.write(0);
  Serial.println("Arm has been tared");
}

void Arm::getArmPosition() {
  Serial.print("Shoulder Position: ");
  Serial.print(ShoulderEncoder.read());
  Serial.print("Elbow Position: ");
  Serial.println(ElbowEncoder.read());
}

```

Unfortunately, there appears to be some sort of problem with passing the Encoder object. I am getting the error:

> Compilation error: no matching function for call to 'Arm::Arm(int, int, int, int, Encoder&, Encoder&)'

I am definitely a noob when it comes to coding, so thanks in advance for what is probably a simple problem.

# Answer
> 1 votes
You're jumping backwards and forwards between pointers and the objects themselves. Change it to pass pointers to the arm constructor and consistently use pointers (or pass a reference and always use that, just be consistent). This would be something like:

```
    // main code, pass a pointer rather than the object itself
    Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, &ElbowEncoder, &ShoulderEncoder);

    // header
    public:
      Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder);

    // cpp
    Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder) {

      pinMode(ShoulderUpPin, OUTPUT);
      pinMode(ShoulderDownPin, OUTPUT);
      pinMode(ElbowUpPin, OUTPUT);
      pinMode(ElbowDownPin, OUTPUT);

      _ShoulderUpPin = ShoulderUpPin;
      _ShoulderDownPin = ShoulderDownPin;
      _ElbowUpPin = ElbowUpPin;
      _ElbowDownPin = ElbowDownPin;
      this.ElbowEncoder = ElbowEncoder; // use 'this.' to indicate the class private variable since it's the same name as the passed parameter.
      this.ShoulderEncoder = ShoulderEncoder;
    }

```

And then within your class, since ElbowEncoder is a pointer rather than the encoder itself, use `ElbowEncoder->method()` rather than `ElbowEncoder.method()`

Personally, I'd restructure it a little. Why create the encoders at the top level when they are only used within the arm class? Create them in the arm class instead:

```
    //in .h
    public:
      Arm(int ShoulderUpPin, int ShoulderDownPin, int ShoulderEncoderPinA,int ShoulderEncoderPinB,
          int ElbowUpPin, int ElbowDownPin, int ElbowEncoderPinA, int ElbowEncoderPinB);

    private:
      Encoder ShoulderEncoder;
      Encoder ElbowEncoder;

    // in .cpp
    Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ShoulderEncoderPinA,int ShoulderEncoderPinB,
             int ElbowUpPin, int ElbowDownPin, int ElbowEncoderPinA, int ElbowEncoderPinB) :
                 ShoulderEncoder(ShoulderEncoderPinA,ShoulderEncoderPinB),
                 ElbowEncoder(ElbowEncoderPinA,ElbowEncoderPinB) {
       // constructor code
    }

```

This will create the encoders as private to the arm as soon as you call the arm constructor. Especially handy if you want to have more than one arm.

---
Tags: class, pointer
---


# Question
Title: A library issue with ArduinoOTA for MKR1400GSM
For the past years I've been using ArduinoOTA along with ArduinoHttpClient on MKR1400 for updating the bin on the fly from a remote web server.

Even without ArduinoOTA's official support for GSM, it has been working like a charm. All it took was adding a condition to ArduinoOTA.h to accept MGRGSM (thanks Juraj) and some playing around with the code to ensure successful operation:

```
#elif defined(_MKRGSM_H_INCLUDED)
ArduinoOTAClass <GSMServer, GSMClient> ArduinoOTA;

```

Unfortunately, the other day I went ahead and updated by IDE's libraries without first backing them up and now I lost the ability to perform successful OTA.

What I have done so far is to step back with libraries versions and check the dates of the lib updates (I found a point in time when I knew I compiled a good version before the lib has been updated) but so far nothing, the OTA process starts and it bricks the board.

Any idea? Thanks!

# Answer
> 2 votes
Arduino made changes in platform.txt files for IDE 2.0 pluggable monitor system, which is a system to detect COM ports, network ports and other means to upload to Arduino.

While they did the changes they forgot to test the OTA support with IDE 1 so they broke OTA in AVR and SAMD core. The affected versions of core are AVR 1.8.4 and SAMD 1.8.12.

Arduino already fixed the error in platform.txt in both cores and AVR core already has a new release 1.8.5 with the fix. ~~The SAMD core doesn't have a new release yet. You can apply **the fix** to your 1.8.12 installation, or return to 1.8.11 version~~. EDIT: SAMD core 1.8.13 is already available too.

EDIT: Or you can use the 'fake programmer' method which doesn't require network port to be detected by the IDE and has a separate configuration.

# Answer
> -1 votes
I tried all over again, IMHO it's not possible to get a large bin file uncorrupted directly on a SD card. The only way i see is first into the internal memory of the modem and then on the SD card. I made a example: https://github.com/CptHolzschnauz/Arduino-MKR-1400-OTA-Update

---
Tags: ota
---


title: UDP Packet Loss

text:
# Question
Title: UDP Packet Loss
I have an application on a PC that sends **10 UDP packets** to an Arduino Portenta board. When sending packets with no delay, half of them are lost. Wireshark shows the packets are correctly sent by the PC. If I busy-wait 1ms between each message on the PC, the Arduino receives everything.

I tried to disable the processing done when receiving a message, but it doesn't help.

I know UDP is not a reliable protocol. Still, having half the packets lost while the PC is directly connected to the Arduino is surprising. I'm only trying to send 10 packets!

Is there an option to increase the receive buffer? I would have tried increasing SO\_RCVBUF.

Any other idea?

Thank you

# Answer
> 2 votes
UDP does not guarantee delivery.

https://en.wikipedia.org/wiki/User\_Datagram\_Protocol

> It has no handshaking dialogues, and thus exposes the user's program to any unreliability of the underlying network; there is no guarantee of delivery, ordering, or duplicate protection.

You have chosen a protocol that is inherently not guaranteed to be delivered, and thus you have to work around it by:

* slowing transmission
* accepting that not all packets will be received
* some other mechanism

---
Tags: ethernet, performance
---


# Question
Title: An error is shown as sendCommand was not declared in this scope.how to rectify it
```
#include <LiquidCrystal.h>
LiquidCrystal lcd(2,8,6,5,4,3);
#include <SoftwareSerial.h>
#define RX 9
#define TX 10
//ESP8266 CODE
String AP = "OPPO F11 PRO";       // AP NAME
String PASS = "bhargav123"; // AP PASSWORD
String API = "DWX3OYUU26GI5IJ7";   // Write API KEY
String HOST = "api.thingspeak.com";
String PORT = "80";
int countTrueCommand;
int countTimeCommand;
boolean found = false;
int valSensor = 1;

SoftwareSerial esp8266(RX,TX);

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600);
 lcd.begin(16,2);
 lcd.setCursor(0,0);
 lcd.print("Cable");
 delay(1000);
 lcd.setCursor(0,1);
 lcd.print("Fault Detection");
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A3,INPUT);
  pinMode(A4,INPUT);
  pinMode(A5,INPUT);

//ESP8266 CODE

  esp8266.begin(115200);
  sendCommand("AT",5,"OK");
  sendCommand("AT+CWMODE=1",5,"OK");
  sendCommand("AT+CWJAP=\""+ AP +"\",\""+ PASS +"\"",20,"OK");

}

void loop() {
//ESP8266 CODE
String getData = "GET /update?api_key="+ API +"&field1="+Insulation();
 sendCommand("AT+CIPMUX=1",5,"OK");
 sendCommand("AT+CIPSTART=0,\"TCP\",\""+ HOST +"\","+ PORT,15,"OK");
 sendCommand("AT+CIPSEND=0," +String(getData.length()+4),4,">");
 esp8266.println(getData);delay(1500);countTrueCommand++;
 sendCommand("AT+CIPCLOSE=0",5,"OK");

String Insulation1(){
  if(value>=500 && value1<=700)
  int xoutput=0;
  else
  xoutput=1;
  return String(xoutput);
}

  int value1=analogRead(A0);
  delay(1000);
  lcd.clear();
  lcd.setCursor(0,0);
  Serial.println("value1");
  Serial.println(value1);
  if(value1>=500 && value1<=700)
  {
    Serial.println("Insulation at 1KM is good");
    lcd.print("Insul good 1KM");
    delay(3000);
    lcd.clear();
  }
else
   {
     Serial.println("Insulation at 1KM got damaged");
   lcd.print("Insul damage 1KM");
   delay(3000);
   lcd.clear();
   }
  int value2=analogRead(A1);
  Serial.println("value2 ");
  Serial.print(value2);
  delay(1000);
  if(value2>=500 && value2<=700)
  {
    Serial.println("Insulation at 2KM is good");
    lcd.print("Insul good 2KM");
    delay(3000);
    lcd.clear();

  }
else{
   Serial.println("Insulation at 2KM got damaged");
  lcd.print("Insul damage 2KM");
   delay(3000);
   lcd.clear();
}
    int value3=analogRead(A2);
    Serial.println("value3 ");
    Serial.print(value3);
    if(value3>=1000)
    {
      Serial.println("short circuit at 1KM ");
      lcd.print("Short at 1KM");
      delay(3000);
      lcd.clear();
    }
    int value4=analogRead(A3);
    Serial.println("value4 ");
    Serial.print(value4);
    if(value4<=1000)
    {
      Serial.println("Open circuit at 1KM");
      lcd.print("open at 1KM");
      delay(3000);
      lcd.clear();

    }
    int value5=analogRead(A4);
    Serial.println("value5 ");
    Serial.print(value5);
    if(value5>=1000)
    {
      Serial.println("short circuit at 2KM");
      lcd.print("short at 2KM");
      delay(3000);
      lcd.clear();

    }
    int value6=analogRead(A5);
    Serial.println("value6 ");
    Serial.print(value6);
    if(value6<=1000)
    {
      Serial.println("open circuit at 2KM");
      lcd.print("Open at 2KM");
      delay(3000);
      lcd.clear();
    }

//ESP8266 CODE
    void sendCommand(String command, int maxTime, char readReplay[]) {
  Serial.print(countTrueCommand);
  Serial.print(". at command => ");
  Serial.print(command);
  Serial.print(" ");
  while(countTimeCommand < (maxTime*1))
  {
    esp8266.println(command);//at+cipsend
    if(esp8266.find(readReplay))//ok
    {
      found = true;
      break;
    }

    countTimeCommand++;
  }

  if(found == true)
  {
    Serial.println("OYI");
    countTrueCommand++;
    countTimeCommand = 0;
  }

  if(found == false)
  {
    Serial.println("Fail");
    countTrueCommand = 0;
    countTimeCommand = 0;
  }

  found = false;
 }

 }

```

# Answer
First thing: format your code properly. Statements that are at the same nesting level should have the same amount of indenting. If you find this rule too hard to follow, you can try the auto-format feature of the Arduino IDE (Ctrl-T).

Once the code is properly indented, its whole structure should become clear. Here is what it looks like:

```
// Preprocessor directives and declarations of variables...

// Definition of the function "setup":
void setup() {
  // Some code...

  sendCommand("AT",5,"OK");
  sendCommand("AT+CWMODE=1",5,"OK");
  sendCommand("AT+CWJAP=\""+ AP +"\",\""+ PASS +"\"",20,"OK");
}

// Definition of the function "loop":
void loop() {
  // Some code...

  // Nested function definition:
  String Insulation1() {
    // ...
  }

  // More code...

  // Nested function definition:
  void sendCommand(String command, int maxTime, char readReplay[]) {
    // ...
  }
}

```

The C++ language does not support nested function definitions. Even if it did, using in `setup()` a function that is only defined within `loop()` would not work. The solution is simple: move the definition of `sendCommand()` out of `loop()`, into the global scope. Oh, and remove the definition of `Insulation1()`: it is never used.
> 2 votes

---
Tags: arduino-uno, esp8266
---


title: Decoding 2.4G RF remote controller?

text:
# Question
Title: Decoding 2.4G RF remote controller?
There is tons of information on how IR remote controls work and how to use an Arduino to decode those signals and use any IR remote to suit your project. But I couldn't find much info about 2.4G RF remotes.

I want to control a string of addressable LEDs and cycle through different patterns using one of these 2.4G RF remotes

Is it possible to use these remotes with Arduino? If yes, how can I read the signals and assign tasks to different buttons on the remote?

# Answer
The usual approach for 2.4 GHz is to open the product, identify the radio chip, and use a USB logic analyzer on the SPI bus that usually connects it to the MCU to capture the configuration and data traffic, and figure out what the configuration register accesses mean from the radio chip data sheet.

The occasional appearance of combined MCU/radio parts prevents that approach, but often that is only used on one end of the link and the other will still have a distinct MCU and radio with an SPI bus in between.

This is heavily practiced in the radio control community, as people want to use their nice transmitters to fly cheap toys. And there is code out there to transmit compatibly with some of the odder chips like the X297, using more common ones like the NRF24L01 or its workalikes from Beken, etc.

A key advantage of SPI sniffing versus over-the-air sniffing is that the usually implemented channel-hopping doesn't mean you loose the signal ever time it moves to a new channel - and you actually get to the see the frequency registers being written. To capture a hopping scheme over the air, you would need something more like a spectrum analyzer to figure out the sequence, and then have software track the signal while you attempt to figure out the data. However, a remote which only sends occasional button presses may not use hopping in the way something sending data continuously (like an R/C set, or possibly a keyboard/mouse) would.
> 2 votes

# Answer
I was having same issue and at the end of the day I have made it working. For the communication I have used openmili library (project started by Henryk Plötz who has reverse engineered protocol for communication of these remotes). This didn't work with new remotes as they have changed couple of things:

* Listens on a different channelset (this was true of different bulb types among the old bulbs too). The new bulbs use channels 8, 39, and 70.
* Different PL1167 syncword. It uses 0x7236 , 0x1809 .
* Packets have 9 bytes instead of 7.
* Packets are scrambled. The same command can look completely different.

(information taken from Chris Mullins blog)

Confirmation of these info I have found in ESP8266 Milight hub project where I have found config for remotes (https://github.com/sidoh/esp8266\_milight\_hub/blob/master/lib/Radio/MiLightRadioConfig.cpp)

In my case I was using rgb+cct remote so it tells me that I should use `0x7236, 0x1809` as syncwords, packet length `9` and channels `8, 39, 70`.

Applying those changes I was able to get data from the remote. One more usefull link.
> 1 votes

# Answer
If it is based on the nRF24L01+ (or the nRF31512C SoC, which is a combined MCU and nRF24L01+ in one chip, and used in most wireless mice and keyboards) then it may be possible to sniff the signal. If not, you're probably not going to have much luck.

You'd be better off trying to hack the existing receiver that is paired with the remote to get usable signals out of it.
> 0 votes

---
Tags: arduino-uno, rf, remote-control
---


# Question
Title: ESP32 restart each minute with SW_CPU_RESET
running an ESP32 (ttgo), I get strange behavior. The unit restarts each minute, around 00 seconds.

I get `12:31:02.861 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)` as reason.

I checked flash frequency is 40MHz (80 seems to lead to same issues)

Anyway, if I start the device at 10:00:34, it will restart at 10:01:00 and then at 10:02:00 and so on ...

running this code: https://github.com/xlyric/pv-router-esp32

Powered by a usb-C phone-power, or on computer usb does the same.

The ttgo is plugged on a board connected to a AC/AC transformer and a current mesure device.

using "esp\_register\_shutdown\_handler", I succed to send a mqtt message "gonna die", it really rise each minute at 00 seconds

# Answer
> 2 votes
The restart reason suggests that the ESP32 restarts upon software restart command. One should go over the code and see where in the code the restart command is sent. For instance starting from line 451 there is following:

```
if (config.restart) {
    //delay(5000);
    Serial.print(PV_RESTART);
    ESP.restart();
  }

```

---
Tags: esp32
---


# Question
Title: Why is sensitivity (threshold) parameter ignored
Analog pontentiometer connected to an Arduino. simplest possible setup. The goal is to send a message over `Serial` whenever the value changes.

I do not want to spam the Serial connection to much, so the value has to change by at least `20` (sensitivty threshold) before a message Packet is sent.

However, in reality a message Packet is sent even if the value changed only by `1`. **Why is sensitivity parameter ignored?**

**edit:** After debugging I can see that it enters the first IF-statement in `read()`. The IF statement evaluates to `0` which is super weird. It shouldn't have entered that IF statement!

**MagicPot.h:**

```
#define MAGIC_POT_MAX_RAW_VALUE_10B     1023
#define MAGIC_POT_MAX_RAW_VALUE_12B     4095
#define MAX_RAW_VALUE_DEFAULT           (MAGIC_POT_MAX_RAW_VALUE_10B)

class MagicPot
{
    public:
        typedef void (*callback_fn)();
        MagicPot(uint8_t pin, uint16_t minRead = 0, uint16_t maxRead = MAX_RAW_VALUE_DEFAULT, uint16_t maxRawRead = MAX_RAW_VALUE_DEFAULT): pin(pin), minRead(minRead), maxRead(maxRead), maxRawRead(maxRawRead) {};
        void begin();
        bool read(uint8_t sensitivity = 5);
        uint16_t getValue();
        uint16_t getRawValue();
        uint8_t pin;

    private:
        uint16_t minRead;
        uint16_t maxRead;
        uint16_t maxRawRead;
        callback_fn onChangeCallback;
        uint16_t value;
        uint16_t rawValue;
};

```

**MagicPot.cpp:**

```
void MagicPot::begin()
{
    this->onChangeCallback = nullptr;
    this->value = 0;
    this->rawValue = 0;
    pinMode(this->pin, INPUT);
    this->read(0);
}

bool MagicPot::read(uint8_t sensitivity)
{
    this->rawValue = analogRead(this->pin);

    uint16_t value = map(this->rawValue, 0, this->maxRawRead, this->minRead, this->maxRead);

    if (abs(value - this->value) > sensitivity)
    {
        this->value = value;
        return true;
    }
    else if (value < sensitivity && this->value != this->minRead)
    {
        this->value = minRead;
        return true;
    }
    else if (value + sensitivity > maxRead && this->value != this->maxRead)
    {
        this->value = this->maxRead;
        return true;
    }
    return false;
}

```

**Arduino code:**

```
MagicPot analogPots[] =
{
    MagicPot(A0),
}

void setup() {
  for (MagicPot& x : analogPots) //arr only contains 1 element
    x.begin();
}
void loop() {
  for (MagicPot& pot : analogPots) //arr only contains 1 element
  {
    if(true == pot.read(20))
      {
        CPPacket* analogPotChangedPacket = new CPPacket(HWEvent::Switch, pot.pin, pot.getValue());
        SendPacket( &myPacketSerial, analogPotChangedPacket);
        delete analogPotChangedPacket;
      }
  }

}

```

**Actual Output: (read from computer(conn via Serial))**

| Type | Error | Target | Value |
| --- | --- | --- | --- |
| Switch | NONE | 54 | 516 |
| Switch | NONE | 54 | 515 |
| Switch | NONE | 54 | 514 |
| Switch | NONE | 54 | 513 |

**Expected Output:**

| Type | Error | Target | Value |
| --- | --- | --- | --- |
| Switch | NONE | 54 | 516 |
| Switch | NONE | 54 | 496 |
| Switch | NONE | 54 | 456 |
| Switch | NONE | 54 | 436 |

# Answer
Consider this subtraction:

```
value - this->value

```

Like in any arithmetic operation, the operands undergo integral promotion, then usual arithmetic conversions. Oversimplifying a bit, “integral promotion” means that types smaller than `int` get promoted to `int`, whereas “usual arithmetic conversions” mean the smaller operand gets promoted to the type of the bigger one. If both types have the same size, the unsigned one wins.

On the Arduino Mega, and `int` is 16 bits. Since the operands of the subtraction are both `uint16_t`, the types are not changed by these implicit conversions. The subtraction is performed with the `uint16_t` type and wraps around modulo 216. If you expect −1, you get 65535.

If you cast one of the operands to `int16_t`, then it will be implicitly converted back to `uint16_t` by the usual arithmetic conversions, and you get the same result.

On your PC, an `int` is 32 bits, thus both operands get implicitly converted to `int` by integral promotion, and you get the expected signed result.

The simple solution to your problem is to turn all your variables to `int16_t`. I suggest you always use signed types by default, and revert to unsigned types when you do need the wraparound semantics of the arithmetic operations (it is useful sometimes).
> 3 votes

---
Tags: arduino-mega, c++, platformio, vscode
---


# Question
Title: Arduino | external power supply and USB at the same time
Arduino | external power supply and USB at the same time

I have got an Arduino Mega 2560 project with many sensor and outputs. Right now I’m supplying it with an external stabilized 5V over the 5V pin (so that I’m using only one power source for all sensor, outputs and Arduino.)

I also have a Raspberry PI connected to the Arduino via USB for flashing and also logging. The Raspberry PI has got an external power supply (and also a board with SSD.)

The problem: If I unplug the RPI external power supply, the Arduino Mega is supplying the RPI with power!!! That’s exactly what I do not want. (Also it’s far too little power for RPI, which isn’t even booting correctly.) Even when I power the Arduino Mega 2560 over the barrel plug (stable 9V), the RPI will be provided with a 5V over the USB cable.

I’m looking in the electrical wiring diagram: I can see the FDN304V The comparison circuit (LM358D) controls this p-channel ***mosfet FPN340P***. But why is it ***USBVCC*** connected if the Gate provides 5V over the LM358D?

I saw this interesting articles but I'm a bit confused:

https://arduino.stackexchange.com/questions/893/what-happens-if-i-power-the-arduino-with-both-the-usb-and-external-power-voltage

What happens if I power the Arduino with both the USB and external power voltage simultaneously?

# Answer
> 2 votes
Assuming your question is more along the lines of "How to prevent back driving a USB connected RPi through an externally powered Arduino".

Consider cutting the positive power wire in the USB cable connected between the RPi and the Arduino.

As for this specific question:

> But why is it USBVCC connected if the Gate provides 5V over the LM358D?

Is it possible you are describing how a N-Channel MOSFET works? The MOSFET in the schematic is a P-Channel MOSFET. The net USBVCC is connected to the net +5V when the P-Channel MOSFET gate is LOW. And is not connected when the gate is HIGH.

---
Tags: power, usb
---


# Question
Title: Have I ruined my Arduino Nano with my terrible soldering (technique and tools!)
So I bought a Arduino Nano and a *very* cheap soldering iron and solder from Alibaba. I was attempting to solder in some connections and failing pretty hard. A small resister popped off when trying to solder a wire to ground. I was pretty good when soldering in high school...but it's been a while since then.

By just plugging it into my computer, I was able to upload a simple program which switches the LED on and off - and that still works.

I'm not clearly not competent enough and I don't have a good enough soldering iron to do surface mount soldering to repair it. So I'm wondering if it'll still do what I want it to do.

My overall aim is to build a simple music player for my 3 year old.

My question is, what does that resistor do? Have I ruined the board?

# Answer
> 1 votes
You haven't answered either of my questions in the comments (where is the component?, what colour is it?) but judging by the position I think it is on the board it is the 0.1 µF capacitor which is part of the reset circuitry. It is designed to briefly pull /RESET low on power-up, or when DTR is asserted.

> If I know what function doesn't work, then I know whether I can still do my project.

Either the board works or it doesn't. There won't be "some function" that won't work. You may have problems resetting it but simply pressing the reset button on the other side (if there is one) should have the same effect.

I suggest you get a better soldering iron with a smaller tip. Also practice soldering a bit. The wire you show in the photo should have a blob of solder around it, not going "raw" into the hole as you have it. I also don't see how you can somehow unsolder a capacitor which is a couple of millimetres away from the pins on the edge of the board. Definitely more practice required.

A common technique with boards like the Nano is to solder a line of pins down each side like this:

Then plug the whole thing into a breadboard and wire up your project on the breadboard. Then you don't need to worry about your soldering technique so much (once you have soldered on the pins, and you can get a friend to help you).

---
Tags: arduino-nano
---


# Question
Title: How to return a value from a non integer input between 0-5 from an output range of 0-320 in map() method
I am experimenting using the map() method in an ArduinoIDE sketch in an attempt to obtain a pixel position for a horizontal meter in the range 0-320 from an input value in the range 0-5. However, when I do this I see in the method that the input must be 'long' type. Here's my example code:

```
  float voltage = 2.5;
  float meterPosition = map(voltage, 0, 5, 0, 320);
  tft.fillRect(0, 0, meterPosition, 10, TFT_GREEN);
  tft.setCursor(10, 70);
  tft.setTextSize(3);
  tft.println(voltage);
  tft.println(meterPosition);

```

But when I run this, despite the input value being 50% of the input range, I expected the meterPosition value to be 160, but it is 128, due I think because the values for this method must be of type 'long' and so the 'float' value is rounded and becomes a 'long' type (I think that's what is happening!!).

I am confused as to the function of the map() method if you are unable to map any range to any other range without using decimals as the input. I am obviously missing something here, so what do I need to change in my map() method code for it to work in my example please, if I am unable to use floats?

Thanks. John

# Answer
> 1 votes
As you already noticed, the `map()` function is meant to work with the `long` data type. Here is its implementation:

```
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

```

If you want to use floats, you could write a version of this function that works with floats. Note, however, that since you are using zeros for both `in_min` and `out_min`, the expression simplifies itself to the point of becoming trivial:

```
float meterPosition = voltage * 320 / 5.0;

```

I would suggest two small changes to this expression though:

* add parentheses around `(320 / 5.0)`: this ratio will then be evaluated at compile-time and you will save an expensive run-time floating-point division
* round to the nearest integer in order to minimize the error: your pixel position will have to be an integer anyway.

With these suggestions, we have:

```
int meterPosition = round(voltage * (320 / 5.0));

```

Do not forget the `.0` in `5.0`, otherwise you would get an integer division.

Note that using `map()` with ranges scaled by a factor 100 is not a terribly good idea: you will waste quite a lot of CPU cycles doing useless computations, and the result will be polluted by two rounding errors instead of one.

# Answer
> 0 votes
Apologies for my stupidity folks! I think I have realised how to do this, it is simply a matter of scaling the input values and input range by 100.

---
Tags: arduino-ide, c++
---


# Question
Title: Arduino uno - 4digit 7seg display via 74HC595 keeps blinking
I am trying to get my 4 digit display (SH5461AS) count from 0 to 9 based on millis() function.

The problem is that it keeps blinking. Even if I display just one number, it shows then it goes black then it shows again, instead of staying on.. Also the upper segment (A) is somewhat delayed. Sometimes it shows, sometimes it does not. I am really not sure what is going on. It is best illustrated in the video: https://youtube.com/shorts/gmbNnvEYq2I

I have arduino UNO R3 hooked up to the 74HC595 8-bit register and from there to the corresponding 'data' pins on the display. It is a common cathode type so I have all of those connected via resistor to the ground.

I appologize for the messy cabeling:

From the display basically all resistors go to ground and all data cables to the register (Q0-DP omitted, segment A-Q7, B-Q6, .., G-Q1 \[decimal number 1=A, 2=B, 3=AB,..\]).

In the register I got VCC, Ground, data cables, EO grounded, serial data-\>arduino D4, storage clock -\> D5, shift clock -\> D6

```
 #include <LiquidCrystal.h>

//LCD
const int rs = 7, en = 8, d4 = 9, d5 = 10, d6 = 11, d7 = 12;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//7SEG DISPLAY
int LATCH = 5;
int CLOCK = 6;
int SERIALPIN = 4;

const byte numbers[] = {
  0b111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111
};

//OTHER

void setup() {
  //LCD
  lcd.begin(16, 2);
  lcd.print("Test!");

  //7SEG
  pinMode(SERIALPIN, OUTPUT);
  pinMode(CLOCK, OUTPUT);
  pinMode(LATCH, OUTPUT);

  //OTHER
  pinMode(13, OUTPUT); // turn off onboard diode
  Serial.begin(9600);
}

void loop() {
  countSeconds();
  delay(1000);
}

void countSeconds(){
    digitalWrite(LATCH, LOW);
    // int number = (millis()/1000%10);
    // Serial.println(number);
    shiftOut(SERIALPIN, CLOCK, LSBFIRST, numbers[0]); //for demonstration purposes display 0
    digitalWrite(LATCH, HIGH);
}

```

Any ideas what's wrong?

# Answer
As @Mat pointed out, the reset pin on the shift register was not connected. I didn't realize I need to anchor it high. Solved all problems, I guess it was resetting unpredictably..
> 1 votes

---
Tags: arduino-uno, shift-register, 7-segment
---


# Question
Title: The Arduino UNO Pin 3V3 have OUTPUT 5V (measured with meter)
I just noticed that my original Arduino UNO on pin 3V3 have 4.98V output. That's odds. That pins should have 3.3V. So I measured the Vout on the voltage regulator LP2985-33DBVR where that pins is connected. And the voltages on Vout are the same of what I have measured on that pin. Does that voltage regulator need to be replaced?

# Answer
> 1 votes
I guess either the regulator has failed creating a short or the 5v rail is shorted to the 3v3 rail elsewhere. Removing the regulator and checking the 3v3 rail is no longer 5v should tell you.

The only time I broke a 3v3 regulator, it failed open, so I don't know how likely it is for a LP2985 to fail short.

You could briefly attach a small load, say a LED and 270 or 330 ohm resistor, to be more certain of the voltage reading.

---
Tags: arduino-uno, power
---


# Question
Title: how to "skip" one parameter of a method with a default value letting it use it's default value, but change parameters after it
**lets say we have a function like this(fictional):**

```
function1(int Z, int X, bool Y=true, int Count=10, int ID=1,bool TeaTime=false);

```

And I want to run this function, but I want to change all parameters, except for "Count", and I want that to keep using it's default value.

**Disclaimer** in this fictional case and in the real case where I faced it I found the default value in the header file and I manually coded it in. but I do not want that, at least not to rely on it, for example if the default value changes in the library then in my code it would still be forced to use that old value. also for ease of use and reducing the chance at problems/mistakes.

**What I tried:** I already tried NULL and DEFAULT, both of them actually let my code work perfectly fine, but I made a test function which had such default values and printed the variables to the serial output and I found that using NULL actually overwrites it to 0 and DEFAULT overwrites it to 1.

I also tried some things like keeping one empty and such but those would give compile faults.

**in short:**

**is there a way to let one parameter somewhere in the middle of the parameters of a function use it's default value while still manually setting the later ones?**

# Answer
> 2 votes
Most intuitive would be builder pattern with "chaining" ability (=returning reference to itself)

Something like (computer version, in arduino remove main, iostream and cout):

```
#include <iostream>

struct SomeParams {
    int        X;
    int        Z;
    bool       Y = true;
    int    count = 10;
    int       ID = 1;
    bool teaTime = false;

    SomeParams(int x, int z) : X{x}, Z{z} {};

    SomeParams & noY() { Y=false; return *this; }
    SomeParams & setCount(int c) { count = c; return *this; }
    SomeParams & setId(int i) { ID = i; return *this; }
    SomeParams & yesTeaTime() { teaTime = true; return *this; }
};

void function(SomeParams const & p) {
    std::cout << "X: " << p.X
              << " Y: " << p.Y
              << " Z: " << p.Z
              << " ID: " << p.ID
              << " count: " << p.count
              << " teaTime: " << p.teaTime
              << "\n";
}

int main() {
    function(SomeParams{45,68}.yesTeaTime().setId(154758).noY());

    // without chaining:
    auto params = SomeParams{4457,5468};
    params.setCount(4515);
    params.setId(15);
    function(params);
}

```

---
Tags: programming, variables
---


# Question
Title: Unlocking Digispark ATTiny85 after flashing it to HID
I made a simple test sketch to make my ATTiny85 emulate a Keyboard and send a sequence of keystrokes.

```
#include "DigiKeyboard.h"
void setup() {
  // don't need to set anything up to use DigiKeyboard
}

void loop() {
  DigiKeyboard.delay(1000);
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.sendKeyStroke(106); // F15
  DigiKeyboard.delay(59 * 1000);
}

```

It worked fine, but now every time I plug it to the USB port on my computer, Windows detects it as a Keyboard and starts typing what I programmed it to type.

Arduino IDE can't reprogram it. When it says "Plug in device now", I do it, but it immediately acts like a Keyboard, not like a programmable ATTiny85.

*Note: Image shows the console output. Code is just a simple blinker.*

Is there any way to save this board? I just want to upload another sketch to it. Maybe some way to rewrite the bootloader or to erase the flash memory entirely.

Also, please give me some advice so I can avoid being locked out again in the future. I really want to use this board as a Keyboard emulator, but I want to be able to reprogram it if necessary.

# Answer
If you can't access the bootloader using USB your remaining option is ISP/ICSP (In-Circuit Serial Programming). I have that digispark board and I have never been able to program it using Arduino's IDE/USB. However, since then I always use both an USBasp programmer and the AVRDUDESS programming tool. With them you can eassily program the controller (they have never failed me). Connect the SPI, +5V, GND and RESET connectors from the ATTINY85 to the programmer, compile the code, program the binaries with AVRDUDESS and voila.
> 2 votes

---
Tags: arduino-ide, attiny85, digispark, hid
---


# Question
Title: How to determine the minimum time for a servo to reach its destination?
We all know servos don't move instantly, which is why it is common to put a delay or a millis() loop whenever you issue a servo.write() command to give it time to reach its target before moving on to the next thing.

What irks me though is that this could be inefficient in situations where the last servo position might be close to its target - you might only need a very short delay in those cases, whereas if it has to sweep the full 359 degrees, you might want more time.

I was disappointed that servo.read() is completely useless for this task (why even include it in the library?) as the following code illustrates:

```
#include <Adafruit_TiCoServo.h>
Adafruit_TiCoServo servo;
const uint8_t PIN_SERVO = 9;

void setup() {
  servo.attach(PIN_SERVO);
  Serial.begin(9600);

  Serial.println("start");
  servo.write(180);
  delay(1000);

  int pos;
  while(pos != 0){
    pos = servo.read();
    Serial.println(pos); // because it only returns what the last write() operation
                         // was sent, it immediately thinks it's at pos 0 and exits.
    servo.write(0);
  }

  Serial.println("Done");
}

```

So that sucks. It seems that my options are:

1. just use a long delay that accommodates the worst-case scenario. I hate this.
2. add a limit switch at the final target position and just read the state of that switch
3. build some kind of elaborate encoder that you can read an absolute angle from or buy a more expensive servo that can tell you this info

For reference the servo I'm playing with is a hobby servo: MG90S

Specifically my question is to confirm that there are no other options available for the MG90S other than what I've listed above.

# Answer
in this case there is mostly one simple solution, and there are some better ones.

**the problem you faced with the method:** First of all, the read() function indeed only returns what you send to it, it mostly is useful for if you want to know what position you send it to in some other part of code(for example can be used to plan what way to go first if you need to go to many points, or if you already are going to the desired position). but since the rc servo has only one signal wire and that wire sends no signals back you don't know what state they are in, rc servo's are mostly for ease of use and not for accuracy and speed, if you need that you can look into a real servo(stepper motor). so yes that function doesn't return the actual position, it returns the desired position.

**Solution1:** the easy software based method: to do this you can either read the datasheet to read the speed in duration per degree or measure it, and then use that to calculate the time it would take. *actually here the Servo.read() function really comes in use, so this is a perfect example of why you would actually sometimes need or want it.*

1. save the duration in miliseconds per degree in a variable.
2. next just before you write to the servo use Servo.read() to get the current theoretical position and use that combined with the position you want to go to calculate the difference in dergees (for example 100 and 40 results in a difference of 60), then multiply that with the duration per step. and you will have the answer of how long a change would take.

**Example1** *warning, untested, might contain spelling mistakes and such*

```
    /* tuned delay Sweep
  This example code is in the public domain.
  No warranty

  modified 27 March 2023
  by Daan V.Loon
*/

#include <Servo.h>
#define DELAYPERDEGREE 2 //this is the value for the sg90 servo from the datasheet(0,12s(120ms)per 60degrees.
#define SAFETYMARGIN 110 //this is to add 10% extra time to wait, to make sure it finishes in time even under load.
//# define is used kind of like a variable that doesn't need to change, purely in code and not in ram
unsigned long waitDuration=0;//variable that shows how long to wait.

Servo myservo;

unsigned long CalcWait(Servo s,int desiredPosition)//method to calculate and return duration to wait in ms 1000ms is 1 s.
{
  int spos=s.read();
  if(spos>desiredPosition){return (((spos-desiredPosition)*DELAYPERDEGREE)*SAFETYMARGIN)/100;}
  else{ return(((desiredPosition-spos)*DELAYPERDEGREE)*SAFETYMARGIN)/100;}
}//end of method

void ServoAndWait(int pos){
  //insert range limiting code here if needed, warning this method doesn't check if you try to use numbers bigger or smaller than your servo or the servo library can actually handle.
  waitDuration=CalcWait(myservo,pos);//call method to update how long to wait, needs to be done before telling the servo to move.
  myservo.write(pos);//tell servo to rotate
  delay(waitDuration);//blocking wait for servo to complete
}
void setup() {
  myservo.attach(2);
  ServoAndWait(180);//rotate to 180 degrees and wait until it should be there+10% with the safetymargin of 110
}

void loop() {
    ServoAndWait(0);
    ServoAndWait(180);
    //this should reult in the famous sweep example, however then at the max speed of your servo, this way you can test it.
    //to optimize speed use a safetymargin far over 100(like 200 or such) then reduce it until you see it just stop or just not stop anymore at the edges.
    //also make sure to first test if your servo can actually handle 0 and 180 degrees, for example first test if it moves if you tell it to go from 10 to 0 and from 170 to 180, not all servos reach the full 180 degree range.

  }

```

**Example2:(no comments)**

```
/* tuned delay Sweep
  This example code is in the public domain.
  No Warranty

  modified 27 March 2023
  by Daan V.Loon
*/

#include <Servo.h>
#define DELAYPERDEGREE 2
#define SAFETYMARGIN 110
unsigned long waitDuration = 0;
Servo myservo;

unsigned long CalcWait(Servo s, int desiredPosition)
{
  int spos = s.read();
  if (spos > desiredPosition) {
    return (((spos - desiredPosition) * DELAYPERDEGREE) * SAFETYMARGIN) / 100;
  }
  else {
    return (((desiredPosition - spos) * DELAYPERDEGREE) * SAFETYMARGIN) / 100;
  }
}

void ServoAndWait(int pos) {
  waitDuration = CalcWait(myservo, pos);
  myservo.write(pos);
  delay(waitDuration);
}
void setup() {
  myservo.attach(2);
  ServoAndWait(180);
}

void loop() {
  ServoAndWait(0);
  ServoAndWait(180);
}

```

**Example3:** *Shorter and more stack overflow alien themed for people who just copy paste or find this clearer*

```
/* tuned delay Sweep
  This example code is in the public domain.
  No Warranty

  modified 27 March 2023
  by Daan V.Loon
*/

#include <Servo.h>
#define DELAYPERDEGREE 2
#define SAFETYMARGIN 110

Servo myservo;

unsigned long CalcWait(Servo s, int desiredPosition)
{
  int spos = s.read();
  return (spos>desiredPosition?((spos - desiredPosition) * DELAYPERDEGREE * SAFETYMARGIN) / 100 : ((desiredPosition - spos) * DELAYPERDEGREE * SAFETYMARGIN) / 100);
}

unsigned long waitDuration = 0;
void ServoAndWait(int pos) {
  waitDuration = CalcWait(myservo, pos);
  myservo.write(pos);
  delay(waitDuration);
}

////---code you would see below, headers and functions and variables above---////
void setup() {
  myservo.attach(2);
}

void loop() {
  ServoAndWait(0);
  ServoAndWait(180);
}

```

These above should be fully functional codes that should work for you, they all work the same. I didn't test it with a servo however, but the logic worked when I tested that. also make sure to change the delay per degree to whatever your datasheet says, in this case the datasheet said 0.12s/60 degrees sg90(very common servo for arduino) so I turned seconds into miliseconds and divided it by 60, so 120/60=2, if you have a much faster servo or need more accurate results for different servos you can use the safety margin to tune, or you can use microseconds in the calculations or such, or just multiply the numbers by 10 and then at the end of the calculations divide it by 10 before returning.

**Then here is also the more difficult hardware version** to do this you can either try to use the servo's buildin hardware and modify the servo with a 4th wire, either add it to the rotation sensor/potentiometer, or add it to the chip if it has a place where you can read it directly, with this you are on your own however since it is very speciffic for every servo.

a more easy way to do this is to use a compactor(or something else that gives you one digital output(typical rc servos will always keep the motor on,and just very rapidly change direction once they are on position, if it actually stops you might just want to read it like a normal digital signal(perhaps do something to protect against motor spikes), and read the wires both standalone instead of comparing them to each other) to compare the voltages on the wires to the motor in the servo, since when it moves one side has a higher voltage than the other side, when it stops, they either are equal or rapidly change to keep position. so you just check for whenever it changes. or if you know the direction you can be even more accurate and fast. this ofcource requires you opening up the servo.

or you can indeed add something like a rotary encoder, no need for a complex one, since you can just count the stripes and if you suddenly don't get changes anymore the servo is also stopped in case you missed some, or you can use something like a small microphone or vibration meter since the servo when it moves, this however may become inaccurate under higher load. just try to avoid reading it with analog signals, since for what you want to use it for analog signals can be really slow.

**also** you might want to look into non blocking delays, it won't make the servo's faster, but it allows you to do other things while the servo is moving so you won't have to wait until it is finished.
> 1 votes

# Answer
Yes, normally servo.read() is pretty useless.

First, check your library with a sketch like this

```
void setup() {
  servo.attach(PIN_SERVO);
  Serial.begin(9600);

  Serial.println("start");
  servo.write(180);
  delay(1000);
  unsigned long start = millis();
  servo.write(0);
  unsigned long duration = millis() - start;
  if (duration <= 1)
     Serial.println("servo.write() returns immediately");
  else {
     Serial.print("servo.write() takes ");
     Serial.print(duration);
     Serial.println(" ms for a 180° move");
  }
}

```

If it returns immediately, you have to really measure somehow the actual speed and eventually follow chrisl's comment.
> -1 votes

---
Tags: servo
---


# Question
Title: Incorrect data received on serial communication
I have two **Arduino UNO** connected with two wires, and ground, that exchange informations through **serial data.** The communication is working with INT, but I am having troubles to receive correct characters. Instead of characters I'm only receiving numbers.

I tried every possible combination of `Serial.write()` or `Serial.println()`, with HEX and ascii, but it wouldn't work.

I do not know what I am doing wrong, if anyone could help me, I will appreciate.

**Transmitter :**

```
#include <SoftwareSerial.h>
#define TX 2
#define RX 3
#define ask 3
#define ER_LED 12

String dataline = "605030";
const byte code = 60;

SoftwareSerial syserial(RX, TX); // RX, TX

void setup() {
  // put your setup code here, to run once:
  syserial.begin(57600);
  Serial.begin(57600);
}

void loop() {
  // put your main code here, to run repeatedly:
  //syserial.println(dataline); //NO
  //syserial.println(28, DEC); //ok for numbers

  Serial.println(dataline.length());
  for (int i = 0; i < dataline.length(); i++)
  {
    syserial.print((char)dataline[i]);
  }
  syserial.println();
  //syserial.write(234);
  //syserial.print('<');
  delay(4000);
}

```

**Receiver :**

```
#include <SoftwareSerial.h>
#define TX 2
#define RX 3
const byte ask = 3;
bool com_end;
#define ER_LED 7
#define AC_LED 5

SoftwareSerial syserial(RX, TX); // RX, TX

void setup() {
  // put your setup code here, to run once:
  syserial.begin(57600);
  Serial.begin(57600);
}

void loop() {
  // put your main code here, to run repeatedly:
  while (syserial.available())
  {
    Serial.println(syserial.read());
  }
  delay(100);
}

```

**Serial monitor on whatev b/s:**

```
21:19:36.408 -> 253
21:19:36.408 -> 255
21:19:40.421 -> 253
21:19:40.421 -> 255
21:19:44.495 -> 253
21:19:44.495 -> 255

```

**Monitor with *SySerial* on 57600 b/s:**

```
21:23:29.317 -> 241
21:23:33.308 -> 241
21:23:37.338 -> 241
21:23:41.328 -> 241

```

**Monitor with *SySerial* on 300 b/s:**

```
21:27:03.444 -> 255
21:27:07.731 -> 255
21:27:12.095 -> 255
21:27:16.335 -> 255
21:27:20.635 -> 255

```

**Update :**

I changed the pins on the UNO (TX -\>2)(RX -\> 3), and now i'm getting different numbers again. I must be doing something bad, but I can't understand what.

# Answer
*The communication is working with INT, but I am having troubles to receive correct characters. Instead of characters I'm only receiving numbers.*

Suggest you take a step back because you have code that has not been updated with what you have stated in subsequent comments and it is quickly becoming less clear what is going on.

On each UNO Use pins 2,3 and GND. **Don't connect anything else to either UNO.**

UNO ONE pin **2** connects to UNO TWO pin **3**

UNO ONE pin **3** connects to UNO TWO pin **2**

UNO ONE GND to UNO TWO GND

on UNO ONE run this code:

```
// RECEIVER
#include <SoftwareSerial.h>
SoftwareSerial SSerial(2,3); // RX, TX
void setup() {
  Serial.begin(9600); // Arduino monitor hardware Serial
  SSerial.begin(9600);
}
void loop() {
  // display whatever comes in on the software serial to the Arduino monitor (the hardware serial)
  if (SSerial.available()) {
    Serial.write(SSerial.read());
  }
}

```

on UNO TWO run this code

```
// SENDER
    #include <SoftwareSerial.h>
    SoftwareSerial SSerial(2, 3); // RX, TX
    void setup() {
      SSerial.begin(9600);
    }
    void loop() {
      SSerial.println("Simple Arduino SoftwareSerial Test");
      delay(1000);
    }

```

Open the serial monitor on UNO ONE and you will see "Simple Arduino SoftwareSerial Test" printed every second.

If you can't get that far, you have some other problem.

Are you using two UNOs on two different computers? Are you using two UNOs on one computer, that is; running two instances of the IDE (may depend on OS - I do that all the time on Win 7 but I don't know about other OSs)?

See if you can get this far first and I think it will be easier to get the rest fixed.
> 0 votes

---
Tags: arduino-uno, serial, softwareserial
---


title: ESP32 start BLE after deep sleep

text:
# Question
Title: ESP32 start BLE after deep sleep
I'm new to using the esp32 as a microcontroller. I'm currently working on a so-to-say remote control. Since I want to use the esp32 with an external battery I need to put it in deep-sleep after I pressed some buttons to preserve battery.

All that works fine I've connected a small touchpad to put the esp32 into deep sleep mode using the `esp_deep_sleep_start()` function . The controller itself goes to sleep and can be woken up using the following 2 lines:

```
  touchAttachInterrupt(T0, wakeCallback, TOUCH_THRESHOLD);
  esp_sleep_enable_touchpad_wakeup();

```

In order to communicate with my Raspberry Pi 'Base Station' I decided to use BLE. My server is configured the following way (where `bleServer`, `bleCharacteristic` and `bleService` are global variables):

```
  BLEDevice::init("esp-32-remote");
  bleServer = BLEDevice::createServer();
  bleServer->setCallbacks(new ServerCallbacks());

  bleService = bleServer->createService(SERVICE_UUID);
  bleCharacteristic = bleService->createCharacteristic(
                        CHARACTERISTIC_UUID,
                        BLECharacteristic::PROPERTY_READ |
                        BLECharacteristic::PROPERTY_WRITE
                      );

  bleCharacteristic->addDescriptor(new BLE2902());
  bleService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

```

Upon regular restart using the buttons everything works fine. I can connect to the device using python and the bluepy library.

If I now wake the controller I can't do anything anymore. The `setup()` function gets called and there are no errors, nor does the controller crash due to any code errors (seemingly).

Then the loop function gets called once, and thats it. I can't connect to the device anymore until I press the hardware reset button.

The questions that arise are:

* might there be some error in the way I shutdown the bluetooth module?
* Does the loop function work after being woken up from deep sleep?

Maybe one of you has an idea regarding my issue. If there are more information that I need to provide, don't hesitate to tell me, I'm new to the whole mcu topic and I don't know whats best to provide here.

# Answer
> 2 votes
Does the loop function work after being woken up from deep sleep? YES

loop function isn't magical. its just a function that gets called over and over. In other words, if it gets called once, it can be called again except if

* it did something to deactivate itself
* never reached the end

during that first call. Check that you are not activating some sort of state inside the loop or going into a blocking call awaiting a signal that is never sent.

For good measure, make sure to reset all your variables to their expected states - expecting something to be 0 or set via the original definition may be insufficient. This is something that occurs on a power reset so if reset is making it work again, thats a likely culprit. Use a bare minimum of code in the loop for debug so you can figure it out.

# Answer
> 0 votes
There's a good tutorial here on how to connect the BLE server client to the ESP32. And a Good fix here for reconnection issues.

Below is a piece of prototype code I wrote for BLE server client connectivity:

```
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      deviceDisconnected=false;
      interface->onBoardLED->led[0] = interface->onBoardLED->LED_GREEN;
      interface->onBoardLED->statusLED(100, 1);
      BLEDevice::startAdvertising();
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
      interface->onBoardLED->statusLED(100, 1);
      interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
      interface->onBoardLED->statusLED(100, 1);
      interface->onBoardLED->led[0] = interface->onBoardLED->LED_BLUE;
      interface->onBoardLED->statusLED(100, 1);
      pServer->getAdvertising()->start();
    }
};

class pCharacteristicTX_Callbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        String msg="";
        mserial->printStrln("*********");
        mserial->printStr("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++) {
           msg=msg+String(rxValue[i]);
           mserial->printStr(String(rxValue[i]));
        }

        mserial->printStrln("");
        mserial->printStrln("*********");

        //valueReceived=msg;
      }
    }

    void onRead(BLECharacteristic *pCharacteristic) {
      mserial->printStrln("*********");
      mserial->printStr("onRead...");
      pCharacteristic->setValue("OK");
    }

  };

class pCharacteristicRX_Callbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      mserial->ble=false;

      if (rxValue.length() > 0) {
        String msg="";
        mserial->printStr("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++) {
           msg=msg+String(rxValue[i]);
           mserial->printStr(String(rxValue[i]));
        }

        msg.trim();
        $BLE_CMD=msg;
        mserial->ble=true;
        newCMDarrived=true;
      }
    }

    void onRead(BLECharacteristic *pCharacteristic) {
      mserial->printStrln("*********");
      mserial->printStr("onRead...");
      pCharacteristic->setValue("OK");
    }

  };

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

// Create the BLE Device
  BLEDevice::init("Smart Concrete Curing");  // Give it a name

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic

  pCharacteristicTX = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );

  pCharacteristicTX->addDescriptor(new BLE2902());

  pCharacteristicRX = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_RX,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  pCharacteristicTX->setCallbacks(new pCharacteristicTX_Callbacks());
  pCharacteristicRX->setCallbacks(new pCharacteristicRX_Callbacks());

  interface->init_BLE(pCharacteristicTX);

  // Start the service
  pService->start();

```

on this particular code, I'm using light sleep , so to go to sleep :

```
      btStop();
      delay(1000);
      WiFi.disconnect(true);
      WiFi.mode(WIFI_OFF);

      changeMcuFreq(interface, interface->MIN_MCU_FREQUENCY);

```

and to wake up :

```
changeMcuFreq(interface, interface->WIFI_FREQUENCY);
btStart();

```

---
Tags: bluetooth, nodemcu, esp32, ble
---


title: How to use ESP_LOGx?

text:
# Question
Title: How to use ESP_LOGx?
I can't get the logging to work on the ESP32. Here is my example:

```
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include <esp_log.h>

void setup() {
  Serial.begin(115200);
  ESP_LOGE("Test", "This is a test!");
  delay(1000);
}

void loop() {
  ESP_LOGE("Test", "This is a repesting test!");
  delay(1000);
  Serial.println("Serial.print");
  delay(1000);
}

```

It only prints `Serial.print` every two seconds, but not the log messages.

# Answer
> 2 votes
Thanks to hcheung! I had to set the `Core Debug Level` in the `Tools` menu.

---
Tags: arduino-ide, esp32, logging
---


# Question
Title: Read status of digital pin 11, when it is set as OUTPUT
I have set `pin 11` as output. `pinMode(11, OUTPUT);`

However, I want to be able to read its state (if it is `HIGH` or `LOW`), however since it is set as `OUTPUT`, I am not able to use `digitalRead()`.

I found this online though:

```
Serial.println(bitRead(PORTD,3));
//Reads bit 3 of register PORTD which contains the current state (high/low) of pin 3

```

If I want to read the state of `pin 11` then this: `Serial.println(bitRead(PORTD,11));` will be enough? Or do I have to change the `PORT` as well?

# Answer
> however since it is set as OUTPUT, I am not able to use digitalRead().

Where did you hear that? `digitalRead()` will return the state of a pin set to OUTPUT mode. (In that case, it will be the state you last set it to). As a demonstration, this is a common idiom for inverting the state of an output pin:

```
digitalWrite(LEDPIN, !digitalRead(LEDPIN));

```
> 2 votes

---
Tags: pins
---


# Question
Title: Does Arduino Zero need to be switched between USB EDBG and JTAG port debug use?
I wanted to compare the debug output of the Arduino Zero when connecting via two different debug paths.

1. Via the embedded debugger (EDBG) connected to Arduino IDE via USB
2. Via the JTAG hardware connector J100 to a Black Magic Probe and GDB

The two paths being compared are shown on the Zero Schematic:

Using the Blink.ino compiled for debug, the EDBG works as expected into the Arduino IDE 2.0.4 debugger via USB.

However using the same sketch with the JTAG hardware port to a black magic probe fails to connect, reporting "Target voltage: 1.0V".

```
rowan@rowan-ThinkPad-X1-Carbon-4th:/tmp/arduino/sketches/1EBCACBEAD6C08902D692E87F523B56E$ arm-none-eabi-gdb Blink.ino.elf
GNU gdb (GNU Arm Embedded Toolchain 10.3-2021.10) 10.2.90.20210621-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from Blink.ino.elf...
(gdb) target extended-remote /dev/ttyACM1
Remote debugging using /dev/ttyACM1
(gdb) monitor jtag_scan
Target voltage: 1.0V
JTAG device scan failed!
Failed
(gdb)

```

The same probe and setup successfully debugs an Arduino Due. Acknowledging different processors on the two boards.

The JTAG connector is correctly oriented.

Is a switching action needed to enable one debug path or the other, or is something else wrong?

**Update 2023-04-01:** I bought an SWD breakout board so I could get some test leads on without risking bent pins (it took a couple of weeks to arrive). The VREF pin on the Zero is 0V when running the debug version of Blink.ino. In comparison the same test rig connected to Due running debug Blink.ino VREF is 3.3V as expected.

Tracing back the Zero JTAG VREF pin connection on the PCB, the connection is as expected compared to the published PCB Layout. It connects to a pin on the Atmel EDBG chip (IC3).

At J100 the schematic (snippet above) labels this connection VCC\_P3V3. However it seems to connect to VCC\_EDBG\_P3V3.

I'm going to spend some time with the Atmel EDBG User Guide

**Update 2023-04-01 #2:** During successful debugging using the USB EDBG to Arduino IDE method, the JTAG (J100) VREF pin remains at 0V.

**Update 2023-04-01 #3:** Refering to the EDBG datasheet section 5. The pin on the EDBG chip (IC3) to which the JTAG Vref pin is connected is (K9) EDBG\_TCK. Noting the orientation is inverted compared to the PCB image.  EDBG\_TCK is described as "JTAG Test Clock pin for EDBG device", and is in the EDBG manufacturing programming group of pins.

**OK, it's clear to me now, that this isn't the JTAG I was looking for, I'll write it up as an answer.**

# Answer
I believe the problem occured because I assumed that J100 on the schematic is the populated JTAG interface. Tracing through the schematics and PCB layout indicate that J100 on the schematic is CN2 on the PCB layout (the JTAG interface with no headers populated). J301 on the schematic is the JTAG interface with headers installed, called CN1 on the PCB layout

J301 (CN1) is for programming the EDBG chip.

J100 (CN2) breaks out JTAG target interface pins, but does not have header installed.

Contrary to the schematic, looking at J100 (CN2) on the PCB laypout and also by visual inspection of the physical PCB VREF pin 1 does not seem to have any connection to +3V3.

Top View:  Bottom View:

Counter to the microscope photo evidence, I do read 3.3V (using multimeter) on the square solder pad of the VREF pin, which matches the schematic. I'm having trouble explaining it though. This is a two layer PCB right?

**Updated 2/4/2023: My conclusion is that the EDBG JTAG port is not useful with the Black Magic Probe as an alternative to EDBG. The J100 (CN2) port seems like it would be usable if it had headers.**
> 0 votes

---
Tags: arduino-zero, debug
---


title: Installing Arduino IDE on Linux

text:
# Question
Title: Installing Arduino IDE on Linux
I downloaded `arduino-1.8.4-linux32.tar.xz` and ran `install.sh` as outlined (the very sketchy instructions) in https://www.arduino.cc/en/Guide/Linux

This seemed to work OK, so I removed 354M of what I thought was the installer, only to discover that I had deleted arduino.

The so-called `install.sh` on closer inspection seemed only to create links into the uncompressed download in my home directory.

The whole process seems very un-Linux like; I had assumed that it would be installed in `/usr/share/` like most Linux programs.

I realise I could extract into `/usr/share/` and set permissions for other users, but surely there must be others who have wanted to do the same. The macOS version seems to have a proper installer; does one exist for Linux?

# Answer
I ran the following to Install the latest Arduino IDE on my Raspberry Pi3. This should work all Pi models. This release enables you to run the Arduino Software (IDE) on many of the mini PC boards based on ARM6+ processors currently on the market, including Raspberry Pi

```
# Installing Arduino IDE
cd /usr/share/
sudo tar xf /home/pi/arduino-1.8.9-linuxarm.tar.xz
sudo chown root:root -R /usr/share/arduino-1.8.9/

# Adding desktop shortcut, menu item and file associations for Arduino IDE
# Each user needs to repeate this
cd
/usr/share/arduino-1.8.9/install.sh

```

There is a similar instruction in MagPi61 except they suggest installation in `/opt`
> 2 votes

# Answer
The problem here is that there are multiple flavours of linux each with their own installation and package management systems - Aptitude, Yum, EMerge, etc.

It is not easy for Arduino to keep up with creating packages for each and every system, so instead they create a single tarball that can be used on any of the systems.

At one point Arduino (or someone, anyway) used to create Debian packages for the IDE and upload them to the main Debian repository - however this has not been done for many years now and the packages in the Debian repositories are very much out of date (1.0.5 IIRC).

If you, as a system manager, choose to deploy the IDE system wide then it is your task to decide how best to do that.

One option is to just copy the contents of the archive to `/usr/share/arduino` and then run `./install.sh` from within that directory.
> 4 votes

# Answer
I wrote an installation instruction for the Arduino 2.0.x IDE over at AskUbuntu.

I chose to install the files in the `/opt` directory, but opinions differ on that topic. The instruction also elaborates on adding desktop links and an icon for Ubuntu flavors.
> 1 votes

---
Tags: arduino-ide, linux
---


# Question
Title: How to Protect GPIO when using long wires?
I want to connect a normal toggle switch with one of the gpios pins of a tasmotized esp01 with a wire about 20 feet in length. When I tried this before, I lost the GPIO pin mostly due to the high current drawn from GPIO because of the long wire. How can I limit current and protect the gpio and esp completely?

# Answer
Thanks for the tips. I have seen one more solution to protect GPIO pins which was never mentioned here. This uses optocouplers. The anode or the cathode of the optocoupler can be connected through a switch to vcc or ground respectively. With respect to the optocoupler a series resistance will also needed to be used. The GPio and ground are connected to the 3 and 4 pins. when the switch is engaged, the 3 and 4 pins are connected.

The limitation is that not all GPIO can be used as some needs physically pulled to ground like Rx pin of esp8266.
> 1 votes

# Answer
You can use a resistor with a transistor in order to control something that requires more power. This will protect your io pin. Values depend on what you are specifically connecting to the io pin.
> 0 votes

# Answer
You don't say how your switch is connected.

The standard way to protect a GPIO pin is with a series resistor and ideally a couple of Schottky diodes to clamp it to the supply rails.

Unless you're expecting particularly high voltages or require high speed data then around 100 ohms in series is reasonable.

The diodes go from the input pin to the processors power and ground pins. They are connected so that if the input is between 0 and 3.3 V they are reverse biased and have no effect. But if the input goes above VCC or below GND then the appropriate diode turns on and clamps the voltage. The series resistor limits the current that can flow in this situation and so prevents the diode from getting overloaded. In the image below this means pin 1 of the BAT54-S (the lower right one) goes to GND, pin 2 to 3V3 and pin 3 to your signal. Watch out, different manufacturers sometimes number the pins in different orders.

In theory the diode isn't needed. The chip will include the equivalent diodes internally. However they aren't particularly good ones and will be more susceptible to failure, counting on them is never a good plan. The external ones will clamp sooner and harder and are easier to replace if something does fry.

Just for clarity the resistor is on the outside of the diode. The signal path is: Outside world - resistor - clamping diode - ESP32 pin.
> 0 votes

---
Tags: esp8266, pins
---


# Question
Title: HC-05 will NOT pair in Master mode (AT+ROLE=1). Same module will pair in slave mode (AT+ROLE=0)
I have a HC-05 Bluetooth module Version (+VERSION:2.0-20100601). I am using Linux Mint Rosa on an Acer laptop

**Section 1 - How it's wired** Wiring

```
HC-05       Arduino
VCC         5V
GND         GND
TX          pin 1
RX          GND via voltage divider (GND to 2k resistor{2k to HC-05 RX and a 1k resistor} 1k to pin 0)

```

**Section 2 - Sequence to get into AT command state** The sequence I use to get the BT module in AT command state

* Unplug the Arduino Uno
* Unplug both the RX and TX
* Press the button on the HC-05
* Plug in the Arduino
* HC-05 LED flashes 1 time every 2 seconds
* Initialize com ports via Linux terminal - sudo chmod 0777 /dev/ttyACM\*
* Upload an empty sketch
* Plug in the HC-05 RX to Arduino pin 0, and TX to pin 1
* Open the Serial monitor
* Set Both NL & CR and 38400 baud

**Section 3 - AT commands issued** I use the following AT commands with the noted results.

```
AT                                  > OK
AT+ORGL                             > OK
AT+RMAAD                            > OK
AT+VERSION  +VERSION:2.0-20100601   > OK
AT+ADDR     +ADDR:98d3:b1:fd85b0    > OK
AT+NAME=Master1                     > OK
AT+UART  +UART:38400,0,0            > OK
AT+ROLE  +ROLE:0                    > OK

```

NOTE:HC-05 is set to slave and it will pair (see Section 4 below)

THE PROBLEM IS AFTER PAIRING, I RETURN TO AT COMMAND MODE (Section 2) and SET ROLE=1 (Section 5) BUT IT WILL NOT PAIR IN MASTER MODE.

**Section 4 - Pairing** I do the following to pair the HC-05 to my phone

* Unplug the Arduino
* Plug the Arduino back in
* HC-05 LED flashes quickly blink/blink/blink
* Android phone\>settings\>connections\>Bluetooth\>Scan
* 1 device found \> Master1 \> pair 1234
* Android app \> Serial BT terminal\>device\>Master1\>connected
* Once Android app connects:
* HC-05 LED flashes blink/blink 2 seconds then blink/blink
* Remove the RX and TX cables from Arduino and put a jumper to connect HC-05 TX to RX (loopback)
* Serial BT terminal\>hello\>send
* Output both green and blue - which means the data was sent via RX and returned via TX.

**Section 5 - change ROLE=0 (slave) to ROLE=1 (Master)** I then follow the same sequence that I used previously in Section 2 to return to AT command state.

Issue the following AT commands

```
AT                      > OK
AT+ROLE  +ROLE:0        > OK
AT+ROLE=1               > OK

```

Since I changed the configuration I unpair the device on my phone. I then follow the same sequence that I previously used in Section 4 to pair the HC-05 to my phone

* HC-05 LED flashes quickly blink/blink/blink
* Android phone\>settings\>connections\>Bluetooth\>Scan - CAN'T FIND THE DEVICE.

If I return to AT Command mode and change AT+ROLE=0 it will Pair.

In Master mode:

* I tried to swap the TX and RX pins - won't pair.
* I tried to pair with the TX and RX removed from the Arduino - won't pair.
* I tried NOT UNpairing the device on the phone but it won't communicate with it via the android app once I change it to Master (Section 5).
* As I mentioned above if I return to AT Command mode and change AT+ROLE=0 it will Pair.

Lastly I have 2 other HC-05 modules and they all fail to pair when set to Master mode, so I'm thinking I'm missing something but can't figure out what it is.

I would appreciate hearing from anyone with the same problem and anyone who can determine what I'm doing incorrectly.

# Answer
You might have already solved your problem, but I just wanted to say that a HC-05 Blueooth module will only connect to a phone when it is in slave mode. The phone acts like a master, and therefore, it can't connect to another master.
> 1 votes

# Answer
I observed that these device do very well in slave more, however, in Master mode, they only connect to themselves ( I mean other HC-05). I have sevceral slave devices ( gamepads, GPS modules, ...) that never get connected, thoug the HC-05 sees them through the INQ command, & accurately returns their address, class, signal force, and their name even. Though, I never succeeded to pair them !! As if they were designed to be used together and never tested with other slave devices !!?
> 0 votes

---
Tags: hc-05
---


title: How do you convert PCM to PWM?

text:
# Question
Title: How do you convert PCM to PWM?
I'm a beginner and I've been developing my own library for a wave player. so far I have the SD card installed and OLED and rotary encoder all connected. I've successfully read the wave chunk and it's data(16bit and 44.1KHz). My question is that the data in wave file is PCM and I wish to play is using 16bit PWM and so how do I convert PCM to PWM?

# Answer
There is no such thing as a PCM file. PCM is completely erroneously used to describe an uncompressed digital audio file. What it actually means is "A file which contains data that can be fed directly to a PCM device without any form of intermediate conversion".

What you have in a "PCM" WAV file is just raw sample data. After your header (usually 44 bytes) you just have 16-bit values representing your sample points, with the two channels interleaved one after the other.

Since PCM is a linear audio representation, the sample data it expects is a simple linear representation of the audio (unlike µLaw or A-law) and with no compression (such as MP3 or FLAC). And that is the exact same data that PWM expects since it too is a simple linear output.

However, none of that matters, because the Arduino simply isn't powerful enough to play your file. Maybe a smaller one (8kHz, mono, 8-bit) would be playable, but not yours. The numbers just don't add up.

There is a PCMAudio example available, but it only works from audio embedded within your program.

There is also a TMRpcm library available which plays from SD card, but is limited to 8-bit mono, though it can supposedly do up to 32kHz sample rate (though I wouldn't want to try doing anything else at all at that rate).

You would be better off using a system more geared towards audio - something with an I2S CODEC chip attached would be the best solution.
> 1 votes

# Answer
You should use an MCU with PWM generators to do that.

The problem with PWM is that the max resolution is quite low (10-bit) so you are effectively limited to 8-bit PCM.

* Use a DSP editor like Audacity to export a 16KHz unsigned 8-bit WAV.
* Import the WAV file as an array of unsigned char.
* Set your PWM freq to the resonant freq of your speaker (eg. 31250Hz)
* Set your PWM timer to fire at 16KHz and set the PWM duty cycle to the next array value.

I use 16KHz sample rate because:

* Reduced memory footprint
* Fewer timer interrupts
* PWM's limited resolution does not seem to benefit from anything above 16KHz
* I use piezo speakers directly wired to PWM pins in H-bridge.
* A separate amp module might benefit from higher sample rates.
> -1 votes

---
Tags: pwm, wave
---