text:
Issues with Polytone Library?
I'm building a device that uses two ultrasonic sensors to detect objects and provide audio feedback in the form of beeps that get faster the closer an object is. I have two speakers, one for each sensor, but the tone command will only do one set of beeps at a time. I tried to get around this with the Polytone Library and polytone command, but when I go to compile, I get an "exit status 1. Error compiling for board Arduino Uno" message. What am I doing wrong? Is there another way to get both sensors beeping  at the same time? Please help!
I'm very new at coding. I tried to put the polytone code in a couple different ways, which I can show if that helps. There's also gyroscope code in there, but I have that working pretty well, so I guess just ignore that.
    #include <digitalWriteFast.h>
#include <Polytone.h>

#include <Wire.h> //library allows communication with I2C / TWI devices
#include <math.h> //library includes mathematical functions

const int MPU=0x68; //I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; //16-bit integers
int AcXcal,AcYcal,AcZcal,GyXcal,GyYcal,GyZcal,tcal; //calibration variables
double t,tx,tf,pitch,roll;

const int anPin1 = 0;
const int anPin2 = 1;
int triggerPin1 = 13;

long distance1, distance2;

//Code Part 2: Level LEDS
// Level LEDs
int levelLED_level = 11;
int levelLED_rollpos = 9;
int levelLED_rollneg = 8;
int levelLED_pitchpos = 12;
int levelLED_pitchneg = 10;
int LED_temp = 7;
Polytone poly;
void setup(){
    Serial.begin(9600);  // sets the serial port to 9600
    pinMode(triggerPin1, OUTPUT);

    Wire.begin(); //initiate wire library and I2C
    Wire.beginTransmission(MPU); //begin transmission to I2C slave device
    Wire.write(0x6B); // PWR_MGMT_1 register
    Wire.write(0); // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true); //ends transmission to I2C slave device
    Serial.begin(9600); //serial communication at 9600 bauds

    pinMode(levelLED_rollneg, OUTPUT);
    pinMode(levelLED_rollpos, OUTPUT);
    pinMode(levelLED_pitchpos, OUTPUT);
    pinMode(levelLED_pitchneg, OUTPUT);
    pinMode(levelLED_level, OUTPUT);
}

void start_sensor(){
  digitalWrite(triggerPin1,HIGH);
  delay(1);
  digitalWrite(triggerPin1,LOW);
}

void read_sensors(){
  /*
  Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
  Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
  */
  distance1 = analogRead(anPin1)*1.35;
  distance2 = analogRead(anPin2)*2.092;
}

void print_all(){
  Serial.print("MB1000");
  Serial.print(" ");
  Serial.print(distance1);
  Serial.print("mm");
  Serial.print(" ");
  Serial.print(" ");
  Serial.print("MB1260");
  Serial.print(" ");
  Serial.print(distance2);
  Serial.print("mm");
  Serial.println();
}

//Front sensor ranges
void midiSlowFront() {
  poly.begin(); // Set up polling timer interrupt
  poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo

  poly.tone(262);
  delay(2000.0);
  poly.end();
}
void midiFront() {
   poly.begin(); // Set up polling timer interrupt
   poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo
   poly.tone(262);
   delay(500.0);
   poly.end();
}
void midiFastFront() {
   poly.begin(); // Set up polling timer interrupt
   poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo
   poly.tone(262);
   delay(150.0);
   poly.end();
}

//Side sensor ranges
void midiSlowSide() {
   poly.begin(); // Set up polling timer interrupt
   poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo
   poly.tone(440);
   delay(2000.0);
   poly.end();
}
void midiSide() {
   poly.begin(); // Set up polling timer interrupt
   poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo
   poly.tone(440);
   delay(500.0);
   poly.end();
}
void midiFastSide() {
   poly.begin(); // Set up polling timer interrupt
   poly.setPins(4,5); // Connect pins 4-5 to positive terminal of speaker/piezo
   poly.tone(440);
   delay(150.0);
   poly.end();
}

void loop(){
    Wire.beginTransmission(MPU); //begin transmission to I2C slave device
    Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false); //restarts transmission to I2C slave device
    Wire.requestFrom(MPU,14,true); //request 14 registers in total

    start_sensor();
    read_sensors();
    print_all();

    //Acceleration data correction
    AcXcal = -950;
    AcYcal = -300;
    AcZcal = 0;

    //Temperature correction
    tcal = -1600;

    //Gyro correction
    GyXcal = 480;
    GyYcal = 170;
    GyZcal = 210;

    //read accelerometer data
    AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) 0x3C (ACCEL_XOUT_L)
    AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) 0x3E (ACCEL_YOUT_L)
    AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) 0x40 (ACCEL_ZOUT_L)

    //read temperature data
    Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) 0x42 (TEMP_OUT_L)

    //read gyroscope data
    GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) 0x44 (GYRO_XOUT_L)
    GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) 0x46 (GYRO_YOUT_L)
    GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) 0x48 (GYRO_ZOUT_L)

    //temperature calculation
    tx = Tmp + tcal;
    t = tx/340 + 36.53; //equation for temperature in degrees C from datasheet
    tf = (t * 9/5) + 32; //fahrenheit

    //get pitch/roll
    getAngle(AcX,AcY,AcZ);

    //printing values to serial port
    Serial.print("Angle: ");
    Serial.print("Pitch = "); Serial.print(pitch);
    Serial.print(" Roll = "); Serial.println(roll);

    Serial.print("Temperature in celsius = "); Serial.print(t);
    Serial.print(" fahrenheit = "); Serial.println(tf);

    if ((roll < 7.00) && (roll > -7.00) && (pitch > -7.00) && (pitch < 7.00)){
    digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, HIGH);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if (roll > 7.01) {
    // Turn on Pos Roll LED
    digitalWrite(levelLED_rollpos, HIGH);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if (roll < -7.01) {
    //Turn on Neg Roll LED
    digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, HIGH);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if (pitch < -7.01) {
    //Turn on Neg Pitch
    digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, HIGH);
    }

    if (pitch > 7.01) {
    //Turn on Pos Pitch
    digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, HIGH);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if ((pitch > 7.01) && (roll > 7.01)){
    digitalWrite(levelLED_rollpos, HIGH);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, HIGH);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if ((roll > 7.01) && (pitch < -7.01)){
     digitalWrite(levelLED_rollpos, HIGH);
    digitalWrite(levelLED_rollneg, LOW);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, HIGH);
    }

    if ((roll < -7.01) && (pitch < -7.01)){
     digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, HIGH);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, LOW);
    digitalWrite(levelLED_pitchneg, HIGH);
    }

    if ((roll < -7.01) && (pitch > 7.01)){
     digitalWrite(levelLED_rollpos, LOW);
    digitalWrite(levelLED_rollneg, HIGH);
    digitalWrite(levelLED_level, LOW);
    digitalWrite(levelLED_pitchpos, HIGH);
    digitalWrite(levelLED_pitchneg, LOW);
    }

    if (tf > 72.00){
      digitalWrite(LED_temp, HIGH);
    }

    if (tf < 72.00){
      digitalWrite(LED_temp, LOW);
    }

    if((distance1 > 24)){
    midiSlowFront();
    }
    if((distance1 < 24) && (distance1 > 12)){
    midiFront();
    }
    if(distance1 < 12){
    midiFastFront();
    }
    if(distance2 > 24){
    midiSlowSide();
    }
    if((distance2 < 24) && (distance2 > 12)){
    midiSide();
    }
    if(distance2 < 12){
    midiFastSide();
    }
  delay(150);
}

//function to convert accelerometer values into pitch and roll
void getAngle(int Ax,int Ay,int Az) {
    double x = Ax;
    double y = Ay;
    double z = Az;

    pitch = atan(x/sqrt((y*y) + (z*z))); //pitch calculation
    roll = atan(y/sqrt((x*x) + (z*z))); //roll calculation

    //converting radians into degrees
    pitch = pitch * (180.0/3.14);
    roll = roll * (180.0/3.14) ;
}

EDIT: Here's the stuff before the error message, my bad!

In file included from C:\Users\Documents\Arduino\polytonetest\polytonetest.ino:1:0:

C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src/digitalWriteFast.h:25:0: warning: "digitalPinToTimer" redefined

 #define digitalPinToTimer(P) \

In file included from sketch\polytonetest.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:180:0: note: this is the location of the previous definition

 #define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )

In file included from C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\Polytone.h:11:0,

                 from C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\Polytone.cpp:7:

C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\digitalWriteFast.h:25:0: warning: "digitalPinToTimer" redefined

 #define digitalPinToTimer(P) \

In file included from C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\Polytone.h:10:0,

                 from C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\Polytone.cpp:7:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:180:0: note: this is the location of the previous definition

 #define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )

libraries\arduino-polytone-master\Polytone.cpp.o (symbol from plugin): In function `Polytone::begin()':

(.text+0x0): multiple definition of `t'

sketch\polytonetest.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

C:\Users\Documents\Arduino\libraries\arduino-polytone-master\src\Polytone.cpp:18:15: warning: type of 't' does not match original declaration [-Wlto-type-mismatch]

 unsigned long t = 0;

               ^

C:\Users\Documents\Arduino\polytonetest\polytonetest.ino:12:8: note: type 'double' should match type 'long unsigned int'

 double t,tx,tf,pitch,roll;

        ^

C:\Users\Documents\Arduino\polytonetest\polytonetest.ino:12:8: note: 't' was previously declared here

C:\Users\Documents\Arduino\polytonetest\polytonetest.ino:12:8: note: code may be misoptimized unless -fno-strict-aliasing is used

collect2.exe: error: ld returned 1 exit status

All that text that comes before the "exit status 1" tells you what is wrong. Without that we know less than you do.

Ohhh, I see! Sorry about that! I will edit the post!


text:
Create a dead zone for joystick
I'm trying to create a dead zone so the joystick will turn the motor off completely when in the center position. It's much too sensitive and will start the motor if barely touched. How could I fix the code so the off position of the joystick is bigger? This is the original code.
#include <Servo.h> //Using servo library to control ESC

Servo esc; //Creating a servo class with name as esc

void setup()
{
  esc.attach(9); //Specify the esc signal pin,Here as D9
  esc.writeMicroseconds(1000); //initialize the signal to 1000
  Serial.begin(9600);
}

void loop()
{
  int val; //Creating a variable val
  val = analogRead(A0); //Read input from analog pin a0 and store in val
  val = map(val, 0, 1023, 1000, 2000); //mapping val to minimum and maximum(Change if needed)
  esc.writeMicroseconds(val); //using val as the signal to esc
}

Please post your code within the code tag for readability. As the compiler error tells you, it appears that your using a variable named 'adc_center' that is not declared. Are you familiar with C++?

When you edit the question, do not remove the tags (\``c++and````) timemage and I have put around the code. There are there for a reason.

Here's how to create the new mapped range with a dead zone. I used Servo.write() which specifies the position in degrees because I couldn't understand what microsecond timings you need, but it should be easy to change it back. I've also added some debug statements to print val as the joystick is moved.
#include <Servo.h>

// Constants for servo angles in degrees.
const int SERVO_MIN = 0;
const int SERVO_MID = 90;
const int SERVO_MAX = 180;

// Constants for raw ADC values of joystick positions.
const int ANALOGUE_MIN = 0;
const int ANALOGUE_MID = 512;
const int ANALOGUE_MAX = 1023;
const int ANALOGUE_THRESHOLD = 100;

Servo esc;

void setup()
{
  esc.attach(9);         // Specify the esc signal pin as D9.
  esc.write(SERVO_MID);  // Move servo to mid position in degrees.
  Serial.begin(115200);
  Serial.println();
  Serial.println("Servo Test");
}

void loop()
{
  static int old_val = -1;   // Initialise to invalid value.
  int val = analogRead(A0);  // Read input from analogue pin A0.

  // Process val if it has changed.
  if (val != old_val)
  {
    old_val = val;
    Serial.print(val);
    Serial.print(", ");

    // Create the dead zone as per Majenko's algorithm.
    val -= ANALOGUE_MID;
    int direction = val < 0 ? -1 : +1;
    val = abs(val);
    val -= ANALOGUE_THRESHOLD;
    if (val < 0) val = 0;

    // Create a new mapped range with a dead zone.
    val *= direction;
    val += ANALOGUE_MID;
    Serial.print(val);
    Serial.print(", ");
    val = map(val, ANALOGUE_MIN + ANALOGUE_THRESHOLD, ANALOGUE_MAX - ANALOGUE_THRESHOLD, SERVO_MIN, SERVO_MAX);
    Serial.println(val);

    // Move servo to new angle in degrees.
    esc.write(val);
  }
}

My method is to separate the direction from the magnitude:

Subtract the "center" value to create a ± range
Use the sign to indicate the direction
Take the abs to give the magnitude
Subtract the "threshold" value
If negative set to zero

So, with example values:
int val = analogRead(0);          // Raw value
val -= 512;                       // Subtract center value (512)
int direction = val < 0 ? -1 : 1; // Direction is either -1 or +1
val = abs(val);                   // Remove the sign
val -= 10;                        // Subtract the threshold (10)
if (val < 0) val = 0;             // Anything below zero is now zero
// val is now 0-501 with a dead zone, and direction is -1 or +1.

Thank you for responding, I tried your modification, now I get an error: 'val' does not name a type.

Then you must have implemented it wrong. That code snippet compiles perfectly fine when wrapped in a function.

I'm sure I did implement it wrong. Could you show me how to wrap it in a function? I am not a coder.

I got it to compile but now the motor doesn't do anything. Could  someone help me with this please?

@edrummer You'll have to edit your question and add an update to it with your new code so that we can see what you have done wrong.

I put the original code up with no modifications. If the snippet will add a dead zone. please tell me where to put it and anything else I need to know to make it work.

Possible typo? int val = analogRead(0); Should that be A0 instead of 0?

@tim The two are one and the same.

How so? int analogPin = A0; Serial.println(analogPin); prints out 14. What am I missing?

@tim You're missing this: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring_analog.c#L53

Note that in your case, the width of the input range (1023) is only very
slightly larger than the width of the output range (1000). You could
take this width difference (23) as the dead zone, and this would
simplify the arithmetics: now the linear parts of your map have a slope
of exactly 1, and you do not need multiplications or divisions.
The map is then:

[0,  500] → [1000, 1500] (slope =1)
[500, 523] →  1500 (slope = 0)
[523, 1023] → [1500, 2000] (slope = 1)

In code:
/*
 * Map:
 *   [  0,  500] -> [1000, 1500]
 *   [500,  523] ->  1500
 *   [523, 1023] -> [1500, 2000]
 */
if (val < 500)
    val = 1000 + val;
else if (val < 523)
    val = 1500;
else
    val = (1500 - 523) + val;

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
L298N Motor Driver not working
I am using a L298N motor driver to connect a motor with NodeMCU. But i did a few tests since a few tests while learning how to control it now when i connect it the motor doesn't even work. Then i removed the nodemcu and just used the motor driver to control the motor, then also it did not work. I don't know why.
I am new to controlling motors and this is my first time.
Also I am using 9v battery to power the motor driver.
l298n- https://www.amazon.in/gp/product/B08SK2ZPYD/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1
nodemcu - https://www.amazon.in/Lolin-NodeMCU-ESP8266-CP2102-Wireless/dp/B010O1G1ES/ref=sr_1_2?dchild=1&keywords=nodemcu&qid=1617973657&s=industrial&sr=1-2

Please post the schematic of your wiring.

Add links to each hardware item.  9V batteries are very poor choice for motors.

@gil so which battery do you suggest. I also suspected that it was not getting enough power.

I do not know your skills, and resources so I decline to make a recommendation. I use LAB power supplies and size batteries when the project if finished.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
How to webClient.write() an image stored on a String?
My application runs on an ESP32-CAM.
It takes pictures and stores to SPIFFS.
Periodically SPIFFS is checked and if images are found:
1- The image is saved to a FTP server
2- The image is summited to a Web Service that returns some informations about the image
3- Values are saved to mySQL
4- The image is deleted from SPIFFS
To read the image from SPIFFS I use the following fragment of code:
String imageName   = file.name();
imageBuffer = "";
while (file.available()){
   imageBuffer += char(file.read());
}

The FTP transfer works perfectly with the following command:
ftp.WriteData((uint8_t*)imageBuffer.c_str(),imageBuffer.length());

The service the image is submited for analizes works OK if I use the command:
webClient.write(fb->buf,fb->len);

But as it is not usable in the current implementation of my project I am trying to work with:
webClient.write((uint8_t*) imageBuffer.c_str(), imageBuffer.length());

I get no errors in return but it just does not work and the web service at the destination returns nothing.
What Am I doing wrong?

What you're doing is treating binary data as text. As soon as you get a 0 byte the string will be truncated.

Your webClient.write() looks fine, but how are you framing this raw data? See How does HTTP file upload work?.

Short knowledge on how to handle this sort of data. "framing raw data"? What does it mean?

@Majenko: A String object does not truncate on the first NUL: it keeps all the bytes you push with +=, and the length() method returns the total number of bytes, including embedded NULs.

Short answer: you can't store raw image data in a String.

"What you're doing is treating binary data as text" Result of internet searchs. As it worked with FTP I tried the same sort or command with webClient but not working. To be honest I do not really understand what I am doing at this binary level. Searching the internet and trying to see what works.

@EdgarBonet I'd expect to end up with a string that has no NULLs in it, since adding a NULL to the end of a string would have no effect.

“framing” is the stuff you put around the data. See the link I provided. @Majenko: yes, you can.

I would like to understand the reason it works with FTP but not with webClient

My poor understanding tells me something to do with spaces and Nulls but do not know how to sort it out.

@EdgarBonet Internally String::concat() uses strcpy(). Ergo it will only copy anything up to the first NULL, replacing any end NULL that's already there.

@Majenko: try it! I did.

I will try it. Thanks

@EdgarBonet I'd rather not, thanks. I stay well away from String and anything to do with it. Never use String for anything. Not only is it generally a bad idea, you just can't trust what it's doing. And regardless: storing raw binary data in a string is asking for trouble.

You should not use String to store binary data.
Instead allocate yourself an array of uint8_t of the right size.
uint8_t *imageData;
size_t len = file.size();

imageData = alloca(len);
file.readBytes(imageData, len);

webClient.write(imageData, len);

With that said, without knowing what the rest of your program is doing I can only surmise that you're just blasting raw data at the web server and hoping it sticks. That's not how web data transfers work. You have to craft the upload page properly as multi-part mime form data. Read this for more information

Hi, thanks, on one side I am submitting it to the FTP library and assume it will handle the flow. The submission to the web service is HTTP so I do not know, but when I use webClient.write(fb->buf,fb->len); it works so I am assuming it is handling the 24K or so bytes of the image. What do you suggest me to do? Thanks

OK, I got it to work as follows:
Not passing the binary anymore, passing the file name so the FTPPost function will do its own reading of the file on SPIFFS and will post in 256 bytes chunks.
The same strategy works with HTTP post to the WebService.
  File picFile = SPIFFS.open(fileName,FILE_READ);
  const size_t bufferSize = 256;
  uint8_t buffer[bufferSize];
  while (picFile.available()) {
    size_t n = picFile.readBytes((char*) buffer, bufferSize);
    if (n != 0) {
      ftp.WriteData(buffer, n);
    } else {
      Serial.println(F("Buffer was empty"));
      break;
    }
  }
  picFile.close();


text:
Dht 11 sensors give null value
void Sensor_value()
{   server.handleClient();
    humidity = dht.readHumidity();
    temperature = dht.readTemperature();
 }

I want to make condition if temperature = null and Humidity= null that means the sensor fails to take reading so I want to return and take value again

both functions readHumidity() and readTemperature() have float as return type. NULL is a value of type pointer, so you will never get NULL as a result from these functions. I think the library returns NAN if it fails to read from the sensor

The way to do this is:
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);

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

See https://www.hackster.io/MisterBotBreak/how-to-use-temperature-and-humidity-dht-sensors-9e5975 and https://stackoverflow.com/questions/40874880/getting-nan-readings-from-dht-11-sensor.
NULL should only be used with pointers.


text:
Use chars in quotes in const char* as name of function
I have been trying for a long time how to use a word declared as const string* word = "xxx" as name of void function declared somewhere below in my code.
Here is example with ssid:
const char* ssid = "name_of_ssid";

void (*name of ssid*) () {

⠀//some code

}

I want to use word declared in const char* in quotation marks as name of function.
It can not be written just void ssid().
Yes, I can set a name of void function manually, when const char* ssid = "CoffeeWifi" I can type void CaffeeWifi() but I want to do that by this way because my code is specific for this option and explaining this code here would be very difficult. When I change array of const char* word from "xxx" to "yyy" I want to  change the name of void from void xxx() to void yyy() as well.
How to do that? What function should I use?
Thank you!

There's no way to do that sort of thing in C++.  What you could do is write another program that produces C++ code that you could then compile.  None of this has to do with Arduino though.

What is it you hope to achieve with this that you couldn't do with just passing the SSID as a parameter to the function?

You could accomplish that with #define instead of assigning a character string.

Maybe you could write some preprocessor macro to achieve it, but I can really think of no good reason why you would want to do this. Anyway, @timemage is right. This has nothing to do with Arduino.

I have feeling, that this is a x-y problem. You have a problem, that you didn't describe, and you think this is the solution, but most likely it isn't. So please describe better, why you want to do this

It sounds like something that, if described well, might be an application for x-macros, but they're not really Arduino-related either.

@timemage is my answer okay ? (edits also allowed)

That's mostly up to O.P.  If you're just wondering about my opinion: it's a reasonable answer to reasonable speculation of the problem that might be motivating their question. But their question as asked isn't addressed by it. It's not always easy to tell to what degree you should to take a charitable interpretation of a person's question or to get them to be precise.  I tend to push for details and less speculation, but there's a line somewhere.  If you're wondering about this sort of stuff, probably the thing to do is to read in the help center and ask on the meta site.

@timemage from my understanding, the OP is looking forward to execute a particular function specifically for a particular use case. Taking it into consideration. I feel that my answer is okay. Adding arguments seems to be a bit troublesome to me in such a situation (which means editing the exemplar function void execute() to accommodate arguments for input into the required function, but that should work just fine only if all functions follow the same argument declaration format).

" explaining this code here would be very difficult. " Try me, I'm always up for learning something.

Such a thing is impossible (unless you keep striving; neither have I tried it yet). Judging from your intention, one thing you can do is to create an array of the names of the functions you'd like to use, another array carrying the pointers to the functions and a programme to call the function according to the input text. I haven't tried it myself, so perhaps I may not sound sensible, but that is the only thing that came to my mind.
An example:
String function_names[3] = {"foo", "bar", "quux"}; /* I am not sure of this syntax;
                                                corrections are welcome */
int *functions[3] = {&foo, &bar, &quux};

String input;

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

void loop(){
        while(Serial.available()){
              String temp_input = Serial.readString()
              input = (temp_input == "")? String("Nothing here") : temp_input;
              execute(input);
        }
        delay(1000);
}

void execute(String func_name){
        for(int i = 0; i < 3; i++){
              if(function_names[i] == func_name){
                     *functions[i]();
              }
         }
}

int foo(){
    Serial.println("foo");
    return(0);
}

int bar(){
    Serial.println("bar");
    return(0);
}

int quux(){
    Serial.println("quux");
    return(0);
}

Being a const char, you can set it at compile time with a define and then use it.
#define fstring(x) #x

const char* ssid = fstring(SSID_NAME) ;

void setup() {
  Serial.println("Start");
  Serial.println(ssid);
  SSID_NAME();

}

void loop() {}

void SSID_NAME (){
  Serial.println(ssid);
}

Instead of using quotes, this uses the stringize operator.

Missing Serial.begin call aside, I don't think this does what you intended it to do.  Knowing how the stringize operator works, I'm having a hard time figuring out what the code was suppose to do just by looking at it.  You should try it yourself in any case.

Tested on a Leonardo (OP doesn't specify), so doesn't need Serial.begin.

I'm not sure about OP's 'why', but I think this achieves the 'what', but in reverse. Instead of using a string as function name, it makes the function name available as a string.


text:
Endurance of Arduino UNO during 24/7 operations and mild power fluctuations
I am designing an automation system for my research project and planning on using Arduino Uno to do the same. The program is to execute simple instructions based on few input parameters and does not need large computational powers. It is estimated it would take 26 minutes to run the program (26-minute cycle*) and it is expected that it would take anywhere from 3 weeks to 2 months to complete the project (1160 - 3300 cycles before reboot)
My question is as follows:

Is the Arduino Uno capable of surviving the extended service expectancy and execute the program correctly?
What is the influence of small voltage fluctuations on the endurance of electronics on the board?
Is a heat sink needed for this application? How to determine the power draw to choose heat sink size?
Is there any fatigue rating for the cyclic running of the program?

I am planning to power the entire system via a regulated 12V 600-watt battery bank and this bank would be periodically recharged.
*By cycle duration I mean the real word time required for completion of one batch. It is estimated that it's required to complete 1160-3300 cycles/batches for the research

Can your application tolerate the MCU resetting via the use of a watchdog timer?

Is the Arduino Uno capable of surviving the extended service expectancy and execute the program correctly?

Yes, it is. Though your program and wiring needs to be stable and correct.

What is the influence of small voltage fluctuations on the endurance of electronics on the board?

Depends on what you call small. As long as you don't enter the brown-out region (where the voltage is so low, that the Arduino goes into reset for safety) or giving a too high voltage to it (See the specifications for that), you should be fine.

Is a heat sink needed for this application? How to determine the power draw to choose heat sink size?

The power draw of the Arduino depends on what you are doing with it. The best way would be to just measure the current of your application. Then you get the power by multiplying current and voltage. Normally you don't need a heatsink with an Arduino. The only part, that can get hot, is the linear voltage regulator. Depending on what you are interfacing with the Arduino, you might need to put a small heat sink on that (12V is a bit on the high side of input voltage for the regulator. It will dissipate the excess 7V as heat, so 7V multiplied by the used current). The microcontroller on the Arduino will not get hot (unless you are doing something terribly wrong).
And you should make sure, that the current for extra peripherals in your project doesn't flow through the Arduino, since that will place an extra burden on the voltage regulator. It should flow past it (means you connect them in parallel to the voltage source).

Is there any fatigue rating for the cyclic running of the program?

No, not really. I think the flash memory (where the program is stored) has a data retention failure rate of less then 1ppm (parts per million) over 20 years. So the program will not be lost, until you plan to run your application a hundret years. Also there is no read limit on the flash memory, only a write limit.

Since the Arduino itself uses a linear regulator, the OP might get nearly twice as much work out of their 12V battery with a switching power supply (even if only stepping down to 6 or 7V to feed the input side of the linear regulator, not bypassing it with a 5V switcher.)  I'm assuming the Arduino draws enough current to make an efficient SMPS possible, and the linear regulator only needs a volt or two of dropout range.

Connecting up their batteries in parallel instead of series to form a 6V bank with twice the mAh capacity would be good in theory, but only if they don't droop much below 6V as they discharge.  (I don't know what kind of low-dropout linear regulator Arduino Uno uses.)  If the battery geometry allows it, 9V or 8V that can droop down to 6V would probably be good.

You are right with your first comment, though I  didn't talk about it in my answer, since the OP didn't ask about the regulator or power supply. For the second comment: It is correct, but we don't know, if the OP uses individual batteries, which would be able to form a 6V bank. He didn't specify what power bank he uses. Only that its 12V

Yeah, I only mentioned it in case it was possible.  Thought you might want to mention something in your answer about selecting a DC->DC converter IC to avoid wasting half the energy in your batteries if that's worth the trouble, and what the minimum dropout for an arduino's linear regulator is, but if not then at least it's in comments.

I see no problems in that. Given the program you write is stable and correct, the Arduino UNO will certainly work without any problems for months. It has an integrated voltage regulator, so you can attach a 12V battery directly and it automatically regulates voltage changes. The CPU and/or flash do not have any "fatigue" problems as long as the program is only read or executed. The program flash has a limited number of write cycles, but that also is far beyond where you'll get problems.
Where I do see a problem is in your use case. You seem to be doing quite complex mathematics with quite a lot of data, when one cycle takes 26 Minutes. You might not have enough RAM on the UNO to do this. It has only 2.5k (that is around 2500 bytes) of RAM. Where do you store the results?

It's actually 2 K of RAM.

@PFM Kindly refer to the edit in the question clarifying the run time.

How much data do you collect per cycle? And how do you intend to store that data (copy it to a PC?)

I have Arduino here powered over year long, still working (running the same loop() again and again) without a glitch and it is not even hand-temperature hot in my living room - I expect it to run flawlessly for lot more years, until I will switch it off :)


text:
Mistake in keyboard typing by Digispark
I want to open notepad by my Digispark. I use this code:
/*  * Generated with <3 by Dckuino.js, an open source project !  */

#include <avr/pgmspace.h>
#include "DigiKeyboard.h"

const char line1[] PROGMEM = "notepad.exe";
const char line2[] PROGMEM = "Hello World!";

char buffer[256];

#define GetPsz(x) (strncpy_P(buffer, (char*)x, 256))
#define KEY_UP_ARROW      0x52
#define KEY_DOWN_ARROW    0x51
#define KEY_LEFT_ARROW        0x50
#define KEY_RIGHT_ARROW       0x4F
#define KEY_LEFT_GUI          0xE3
#define KEY_ESC               0x29
#define KEY_TAB               0x2B

void digiBegin() {
  DigiKeyboard.sendKeyStroke(0,0);
  DigiKeyboard.delay(50);
}

void digiEnd() {
  const int led=1;
  pinMode(led, OUTPUT);
  while (1) {
    digitalWrite(led, !digitalRead(led));
    DigiKeyboard.delay(1000);
  }
}

void printText(char *txt) {
  DigiKeyboard.print(txt);
  DigiKeyboard.update();
}

void setup() {
  digiBegin();

  DigiKeyboard.sendKeyStroke(KEY_R,MOD_GUI_LEFT);

  DigiKeyboard.delay(50);

  // notepad.exe   printText(GetPsz(line1));

  DigiKeyboard.sendKeyStroke(KEY_ENTER);

  DigiKeyboard.delay(100);

  // Hello World!   printText(GetPsz(line2));

  digiEnd();
} /* Unused endless loop */ void loop() {}

My program opened RUN Windows, but instead of typing "notepad.exe" it types "fgl]hY&]p]" and I don't know where am I am making mistakes. Please help me.
I have to write my code similar this:
#include "DigiKeyboard.h"

int pinled = 1;

void setup()
{
    pinMode(3, INPUT);

    digitalWrite(3, HIGH);
}

void loop()
{
    DigiKeyboard.sendKeyStroke(0);

    if(digitalRead(3) == LOW)
    {
        DigiKeyboard.sendKeyPress(KEY_R, MOD_GUI_LEFT);
        DigiKeyboard.delay(10);

        DigiKeyboard.sendKeyStroke(0, 0);

        DigiKeyboard.sendKeyStroke(KEY_C);
        DigiKeyboard.sendKeyStroke(KEY_M);
        DigiKeyboard.sendKeyStroke(KEY_D);
        DigiKeyboard.sendKeyStroke(KEY_ENTER);

        DigiKeyboard.delay(500);

        DigiKeyboard.sendKeyStroke(KEY_I);
        DigiKeyboard.sendKeyStroke(KEY_P);
        DigiKeyboard.sendKeyStroke(KEY_C);
        DigiKeyboard.sendKeyStroke(KEY_O);
        DigiKeyboard.sendKeyStroke(KEY_N);
        DigiKeyboard.sendKeyStroke(KEY_F);
        DigiKeyboard.sendKeyStroke(KEY_I);
        DigiKeyboard.sendKeyStroke(KEY_G);
        DigiKeyboard.sendKeyStroke(KEY_ENTER);
    }
}

What keyboard layout do you have active on your PC?

I tried to clean up the question a bit. You have // notepad.exe   printText(GetPsz(line1));, but I'm guessing these are two separate lines in the code you're actually running; likewise for line2.

when debugging code like yours, always print strings like 1111122222233333 or aaabbbccc .... that way you can tell if characters repeat, even if they are the wrong characters ... in your example, one character appears to repeat, but it us uncertain


text:
Connect ESP32 via MQTT
For a project I am working on, I need to connect my ESP32 board to another server via MQTT protocol. I am using the Mosquitto MQTT Broker and it is presently on my laptop. Following is the test code I am using, which I'll build around this program.

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "*****";              //WiFi Name
const char* password = "********";      //WiFi Password
const char* server= "***.***.**.***";    //RPi or Machine IP on which the broker is

WiFiClient espClient;
PubSubClient client(espClient);

int setup_WiFi(){
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Attempting MQTT connection...");
  client.connect("esp32");
  if (client.connect("esp32")){
      Serial.println("connected");
    }
    else {
      Serial.print("failed, rc=");
      Serial.println(client.state());
    }
    return 0;
}

int reconnect() {
  unsigned long startAttemptTime = millis();
  while (!client.connected())
  {
    Serial.println("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("esp32")){                 //if (client.connect("esp32", MQTT_USER, MQTT_PASS)) {
      Serial.println("connected");
    }
    else {
      Serial.print("failed, rc=");
      Serial.println(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
  return 0;
}

int send_mqtt(){
  setup_WiFi();
  char sss[15]="Hello World";
   if (!client.connected()){
    reconnect();
  }
  client.publish("esp32/test", sss);    //send message
  WiFi.disconnect(true);
  Serial.println("Sent");
  return 0;
}
void setup() {
  Serial.begin(115200);
  client.setServer(server, 1883);   //mqtt server details
  setup_WiFi();
  reconnect();
  send_mqtt();
}

void loop() {
  send_mqtt();
  delay(10000);     //Wait 10 secs before next transmission
}

I tried connection but got this error

Attempting MQTT connection...failed, rc= -2

What am I doing wrong? Any changes I need to make to the .conf file about which I don't know?
Guide me.
Thank You in advance

Here, const char* server= "...*"; , I'm putting the IPv4 address of the machine on which Mosquitto is installed.

Can your laptop ping the ESP32?

Can you connect with an MQTT client running on the broker itself? Do the log files on the MQTT Broker say anything? Are there other MQTT Clients successfully connecting?

@starcat I am able to connect to "localhost". I am using MQTT Explorer to see the connections. Don't actually know if the other devices are connecting, because I haven't tried that and nor do I have the resources. And I am trying to figure out what IP I should connect to.

@Majenko From within the same network, yes I am able to ping.  From a different network (different WiFi), No

From the same network can the ESP32 connect to the laptop?

@Majenko I actually don't know how to test that..could you guide me here? The ESP32 is able to connect to the WiFi and getting an IP too.

The code in your sketch is unlikely to be the problem. It works fine for me after I enter the IP addresses and password for my network.
According to the pubSubClient API documentation, the rc = -2 code returned by client.state() is due to the network connection having failed. As your code has already checked that it is connected to WiFi before trying to contact the MQTT broker, it is probably the communication between the two devices that is the issue, not the WiFi connection itself.  Things to check:

Are both devices are on the same network, and do they have a route to contact each other? From the laptop running the MQTT broker, try running ping XXX.XXX.XXX.XXX (replacing the XXXs with the IP address reported by the ESP32), and check you get a response. You might wish to comment out line 67 of your code so it doesn't disconnect from WiFi after every attempt at sending a message, otherwise you will see lots of lost packets.
Have you got the right IP address for the MQTT broker in your sketch? It should be the IP address for your laptop, not the loopback address, 127.0.0.1.
Can you use another device on the same network to connect to the MQTT server? (e.g. a cellphone running a MQTT dashboard app, or MQTT Explorer in Windows)
Is Mosquitto configured to listen out for remote connections? If you are running v2 of Mosquitto, you have to deliberately configure it to accept incoming connections, otherwise it will only listen to the localhost interface. You would also have to either set up an authentication mechanism or explicitly configure it to allow anonymous connections. This might be why you can connect from the laptop running the broker, but not from other devices.
On the MQTT server, can you see any connection attempts in Mosquitto's log file (/var/log/mosquitto/mosquitto.log)? There might be some error messages that give you further clues.

I tried all that you suggested. Except for "Ping" all the measures failed. I was able to ping.
Sorry for the late response.

So if you can ping the ESP32, and it's using the right address for the MQTT broker, the next thing to check is the broker itself. Could you update your question to include the version of Mosquitto you are running, and a copy of its mosquitto.conf file? What happens when you try to connect to it from a different device on the same wifi?

When connecting another device it gives an error "connection failed"

So it looks like the MQTT broker isn't working. Maybe it isn't configured to allow remote connections. Can you edit your question to include the Mosquitto version number and config file? That would help to debug the problem.

Version is 2.0.11 and link to conf file is here

In that conf file, all the settings are commented out, so Mosquitto is using its defaults. That means you can log on without any authentication, but only from the machine running Mosquitto. It's not listening to your wifi. You need to edit the conf file to allow connections from other devices, and to either set up authentication or explicitly allow anonymous connections. Read the link at Point 4 in my answer to see how.

Thank you so much for your help


text:
Do I need an Microchip ATSAM3X8E Evaluation Kit?
I am intending to use the Arduino Due processors into my own designs. We have a very extensive (dozen of thousands of lines in .c code) sets of Arduino Due functional codes, and now I intend to move into a more solid form shape.
I have the following questions. What i need is some sort of feedback in order to answer those by myself and realize how to proceed.

I understand some of the Fast Speed Serial options in the Microchip IC cannot be tried in the Arduino Due (such as USBOTG?)?. What I actually need is some Serial Speed close to 2Mbps and a USB Programming Port.

Which are the main differences between the Microchip ATSAM3X8E and the Atmel ATSAM3X8E? R: No, they are the same.

I notice there are some functionalities in the Microchip ATSAM3X8E or even in the Atmel ATSAM3X8E not able to be reproduced in the Arduino Due Board?

Do The Microchip ATSAM3X8E IC have its own functionalities not present in the Atmel ATSAM3X8E? R: No, they are the same.

As note, there is a Keil ARM SAM3X-EK Evaluation Kit (also also here with its brochure), with a ATSAM3X8H, which is not the same IC series, but somehow exposes my concern (if real).

If my concern about High Speed Serial is real, how should I evaluate it?

Aren't the chips from Microchip and Atmel now the same, since Microchip bought Atmel quite a while ago?

@chrisl Should but, I am not absolutely sure about real differences for me as user. If there are differences.

there is no difference because it is the same product. only the owner of the factory changed. so please remove this part of the question to make it clearer

@Juraj. Thanks for your clarification. I marks these questions as answered, i did not delete since somebody answered that.

I understand some of the Fast Speed Serial options in the Microchip IC cannot be tried in the Arduino Due (such as USBOTG?)?. What I actually need is some Serial Speed close to 2Mbps and a USB Programming Port.

What would make you think that? The chip is the chip regardless of what board it's soldered to. You have the native USB and you have all the UART connections direct to the chip. The board has no effect on that at all.  2Mbps is nothing. You can go much faster than that.

Which are the main differences between the Microchip ATSAM3X8E and the Atmel ATSAM3X8E?

The label. When Microchip bought Atmel a few years back they bought everything. That includes the Malaysian factories where the Atmel chips are made (a friend of mine had the job of inventory combining and spent quite some time in Malaysia sorting it all out). Microchip ATSAM3X8E chips are made in the same factory by the same people to the same designs on the same machines. It's just they are now labelled "Microchip" instead of "Atmel".

I notice there are some functionalities in the Microchip ATSAM3X8E or even in the Atmel ATSAM3X8E not able to be reproduced in the Arduino Due Board?

Is that a question or a statement. Or aren't you sure? The Due is just a chip on a board with some support circuitry. Everything that is in the chip is there, you can't remove it. There may be the case that a specific pin may not be brought out to a header, but you will have to compare the datasheet with the schematic in that case. The chip is not at fault here.

Do The Microchip ATSAM3X8E IC have its own functionalities not present in the Atmel ATSAM3X8E?

No. The two are 100% identical.

As note, there is a Keil ARM SAM3X-EK Evaluation Kit (also also here with its brochure), with a ATSAM3X8H, which is not the same IC series, but somehow exposes my concern (if real).

The ATSAMA3X8H is not commercially available. It was a specific custom chip made only for the SAM3X-EK kit. It is, essentially, a SAM3X8E with more IO pins and the ability to connect to SDRAM.

If my concern about High Speed Serial is real, how should I evaluate it?

Your concern is not real. Only imagined. The only possibility is that the UART to USB chip used on the Due may not be able to keep up at high baud rates. That has nothing to do with what the SAM3X8E can do, just what the interface to your PC is capable of. You can replace that with an external USB to UART interface if you want, such as an FT232R based interface. That is if it's communication with your PC that you're concerned about, in which case you would be better with the native USB interface as it's not restricted by whatever external hardware is added.

Thank you for all your answers and detailed clarifications.

Open Question: https://arduino.stackexchange.com/questions/72127/sam3x8e-maximum-serial-speed


text:
Serial Communication between ESP8266 and Arduino ( Sofware and Hardware )
I wish to connect an Arduino ( any of 328P family ) which its 5v, with ESP8266 (ESP-01, or even NodeMCU or Wemos D1 mini ) which is 3v3 logic. My goal is that ESP8266 will be in-charge of MQTT messages and other remote abilities, while Arduino board will be in charge of UP/Off/Down rocker switch and 2 relays ( For reliability I rather have this setup ). Both MCU's code is written by me using Arduino
I Know of 2 main ways: voltage divider and level shifter ( and 3rd will be to use a 3v3 logic as pro-mini - but let's leave for now ).
My questions are:
A) Does Rx Tx need a voltage to be the same ( some on-line tutorial ignore this at all )? if so, is it needed both ways ?
B) Some Tutorial mention that using a voltage divider create some communication interference. It is true and/ relevant for use as explained ?
C) Does SofwareSerial library is recommended (again - reliability ).

A) Does Rx Tx need a voltage to be the same ( some on-line tutorial ignore this at all )? if so, is it needed both ways ?

The point is, that often 3.3V MCUs cannot tolerate voltages significantly above that. So connecting 5V can hurt it. I've seen quite a bit of discussion online, if ESP boards are 5V tolerant or not, but I haven't seen a real investigation in this. Often you can very well get away with connecting them directly, but nobody will give you any guarantees about this. If you want to be safe, you need to add some kind of voltage transition from Arduino TX to ESP RX. The other line (ESP TX to arduino RX) is driven by the ESP with 3.3V, which is ok for the Arduino (3.3V is enough for the Arduino to see it as HIGH), so you don't need anything on this line.

B) Some Tutorial mention that using a voltage divider create some communication interference. It is true and/ relevant for use as explained ?

Since a voltage divider is passive, you get extra effects (parasitic capacitance and inductance), which limits the baudrate. Though I still got communication without errors with baudrates up to 115200 (I did not do a thorough investigation, this is just subjective experience). Electronically better would be proper level shifting (which uses transistors), but in most cases a voltage divider also works well. So I would say unless you want to use really high baudrates you are good with a voltage divider. Others can of course also provide their experience on this site.

Does SofwareSerial library is recommended (again - reliability ).

Generally a Hardware Serial interface is always better, since the communication protocol is completely handled in hardware. The code just needs to read and write the individual bytes from/to hardware registers. SoftwareSerial is used, when there is no free to use Hardware Serial interface. And it imposes some extra limits: You can only listen to one SoftwareSerial interface at any give time and you cannot use high baudrates with it (I think 115200 is already too high for it, depending on the used Arduino). Also it depends on the rest of your code (depends on your use of ISRs). So, if you have an unused hardware Serial interface on your Arduino board, you should use that. Otherwise you can use SoftwareSerial.

Just adding a little flesh to @chrisl's excellent answer with some added technical detail:

B) Some Tutorial mention that using a voltage divider create some communication interference. It is true and/ relevant for use as explained ?

The problem here is that the resistors and the input pin's capacitance form a low-pass filter. Too high a resistance and you deform the nice clean square wave of the serial data. This limits the baud rate you can reliably use. Reduce the resistor values and you increase the frequency of the filtering, thus allowing higher baud rates, but at the cost of increased current draw from the TX pin.

Does SofwareSerial library is recommended (again - reliability ).

The problem of SoftwareSerial is twofold: it's very much a "blocking" system, whereby the MCU can't be doing anything else when a byte is being either received or transmitted, and it's very picky about timing, partly because of that blocking.  There are two factors that affect the maximum speed you can use: how fast the MCU can process the incoming signal to work out what it is, and how fast the MCU can process that decoded signal to get it stored in the buffer.
While it's possible to receive reliably a byte at 115200 baud the problem comes when receiving multiple bytes rapidly. The Arduino is not always able to take that received byte and store it in the RX ringbuffer fast enough before the start bit of the next byte arrives, so it misses it. This causes corruption in the data stream.
For this reason I never recommend more than 9600 baud (or maybe 38400 at a pinch) to give the Arduino more time to process the bytes as they arrive. However that then means that more time is spent doing the sending or receiving, which blocks the rest of your program during that time for longer.
Also SoftwareSerial is strictly half duplex: when you're receiving you can't send, and when you're sending you can't receive. It's only really of any use in a "call-response" style protocol where switching between sending and receiving is predictable.

Thank you. Setting speed as 9600 is good enough for me, since esp sends AUX numeric commands to Arduino, in form of 2 digit, and acknowledged message back. So I do not expect nothing fancy.

Regarding softwareSerial, as I said- reliability at top


text:
BLE scanner and WiFi web server on the ESP32 board
I am trying to put BLE and WiFi web server on the same ESP32 board, using Arduino IDE.
However, BLE library is too heavy. It spends about 73% of program size and there no room for WiFi.
Program too big. The size is 1328706 bytes (of a 1310720 byte maximum

These are libraries I am trying to use in the same solution:
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <EEPROM.h>
#include <WiFi.h>

Is there anything I can try to spare program size?
Is there any alternative?

What partition scheme do you use? If you don't use OTA and keep SPIFFS at minimal size, maybe thats enough

@chrisl, I don't set any partitions. I simply installed ESP32 onto Arduino IDE and merged two examples - BLE Scan and WiFi Web Server. Honestly speaking, I know nothing about partitions...

Every board has different tables for dividing the flash memory between the program itself, the SPIFFS for static/persistent files and OTA (over the Air Updates). Please describe, which board ypu have chosen in the IDE and what stettings are selected in the menu for it

@chrisl, Thanks a lot! I chose another partition and now it works.


text:
How to address +HTTPACTION:0,600,0 Not HTTP PDU response
I am using the SIM900A gsm module and trying to connect with my site using a GET request. My issue is that when submitting AT+HTTPACTION=0, I receive a status the response as +HTTPACTION:0,600,0. In this case, the GET request is raised successfully but the response size is 0. In this case, I am not able to fetch a response from the server. The datasheet says the 600 code means "Not HTTP PDU" but I am not aware of how I need to address this. I also sometimes receive code 200, but it is very rare.
following is the response of the AT commands:
AT

OK
AT+COPS?

+COPS: 0,0,"Vi India"

OK
AT+CGDCONT=1,"IP","internet"

OK
AT+CGDCONT=?

+CGDCONT: (1-3),"IP",,,(0),(0)

OK
AT+SAPBR=3,1,"CONTYPE","GPRS"

OK
AT+SAPBR=3,1,"APN","internet"

OK
AT+SAPBR=1,1

OK
AT+SAPBR=2,1

+SAPBR: 1,1,"100.103.109.188"

OK
AT+HTTPINIT

OK
AT+HTTPPARA="CID",1

OK
AT+HTTPPARA="URL","mysite.co.in/newlist.php?K=THS&a=35.97&b=18.84"

OK
AT+HTTPACTION=0

OK

+HTTPACTION:0,600,0
AT+HTTPTERM

OK

Thanks in advance for the support.
Edit I have tried further, I have observed that still, the status code still remains the same 0,600,0 status code. However, when I changed the URL to www.google.com, it returns the expected +HTTPACTION:0,200, xxx status code. Please provide some guidance to get the issue resolve.

How good a signal do you have?

@Majenko  I just checked AT+CSQ returns +CSQ: 31,0, so I understand, signal strength is good enough


text:
Is it possible to compile and upload code witout the IDE?
I just got started with Arduino, and found out that I need the IDE to compile and upload codes, which works perfectly fine. This is my code:
# pragma GCC optimize ("Ofast")

char i = 0 ;
unsigned long time, lastTime ;

void setup() {
    pinMode(LED_BUILTIN, OUTPUT) ;
}

void loop() {
    time = millis() ;

    if (time > lastTime) {
        lastTime = time + 100 ;
        i = ~i ;
        digitalWrite(LED_BUILTIN, i  ? HIGH : LOW) ;
    }
}

But the biggest problem is that the IDE is written in Java and it uses 1 GB of system's memory, and it's very heavy.
So is there a way I can use the Linux command line to compile and upload the code to the Arduino UNO?

You can also try PlatformIO, which offers a similarly integrated experience. It uses VScode which is Electron based, so it's only slightly lighter.

Yes, I haven't used it but on the official page it is mentioned, called Arduino CLI (command line interface), available for Mac and Linux.
https://www.arduino.cc/pro/cli
Excerpt:

Arduino CLI is a command line tool that contains all you need to
easily build applications around the Arduino ecosystem. Parse the JSON
output of the CLI or implement it as an always-on service that accepts
commands via a gRPC interface using your language of choice.
Arduino CLI is the backbone of the Arduino Create Web Editor serving
over a million users.

Also, it's open source and can be found on GitHub at https://github.com/arduino/arduino-cli/releases

I use arduino-cli all the time now. It's so much better than fighting with the IDE - at least for someone like me brought up on programming in vi...

@Majenko vi is a long time ago for me ... at my current project I'm using Visual Studio as I stubbed all Arduino and Arduino library functions so I have a working executable on my PC, and since it's in the same directory as the .ino file I only hit the 'Compile' (and or  upload) button of the Arduino IDE which is the only thing I use. (btw, I'm intending to move to platformio and using ESP32 soon). For me the Arduino IDE is also quite a bad IDE (good for very small one file programs (which as OO programmer is barely the case for me).


text:
Rosserial. Arduino Publishing custom msg (6 float64 values and header) and subscribe Vector3Stamped msg from Arduino mega2560 is not working!
Rosserial Arduino custom msg publisher. I am publishing custom msg (6 float64 values and header) and subscribe Vector3Stamped msg from Arduino mega2560. But is not working!
The error I get is the following (the custom publisher is publishing correctly but the usual subscriber is not working):

Creation of subscriber failed: need
more than 1 value to unpack

When I have the following in Arduino/libraries/Rosserial_Arduino_Library/src/ros.h
 #elif defined(__AVR_ATmega2560__)
       typedef NodeHandle_ <ArduinoHardware, 15, 15, 512, 512> NodeHandle

while the error is different when changing Arduino/libraries/Rosserial_Arduino_Library/src/ros.h to the following:
#elif defined(__AVR_ATmega2560__)
   typedef NodeHandle_<ArduinoHardware, 15, 15, 512, 512,FlashReadOutBuffer_> NodeHandle;

The error I get in this case is the folowing (the custom publisher is not working but the usual subscriber is working)

Creation of publisher failed: need
more than 1 value to unpack
Tried to
publish before configured, topic id
115

My arduino code is the following:
#include <HardwareSerial.h>
#include <ODriveArduino.h>
#include <Wire.h>
#include <ros.h>
#include <std_msgs/String.h>
#include <geometry_msgs/Vector3Stamped.h>
#include <geometry_msgs/Twist.h>
#include <ros/time.h>
#include <mybot/encoderMsgStamped.h>

#define ROBOT_WIDTH (480) //MILLI METER
#define WHEEL_DIAMETER (165.1)  // MILLI METER
#define WHEEL_CIRC (518.676947108) //circumference OF THE WHEEL
#define CPR_ENCODER (90)

HardwareSerial& odrive_serial1 = Serial1;
HardwareSerial& odrive_serial2 = Serial2;
HardwareSerial& odrive_serial3 = Serial3;
//axis0(M0)-left
//axis1(M1)-right
ODriveArduino odrive1(odrive_serial1);
ODriveArduino odrive2(odrive_serial2);
ODriveArduino odrive3(odrive_serial3);

// cmd_vel variables to be received to drive with
float demandx;
float demandz;

// timers for the sub-main loop
unsigned long currentMillis;
long previousMillis = 0;    // set up timers
float loopTime = 100;  //100ms
long forward0;
long forward1;
long turn0;
long turn1;

// position and velocity variables read from the ODrive
long posfl,posfr,posml,posmr,posrl,posrr;

long posfl_old,posfr_old,posml_old,posmr_old,posrl_old,posrr_old;
long posfl_diff,posfr_diff,posml_diff,posmr_diff,posrl_diff,posrr_diff;
float posfl_mm_diff,posfr_mm_diff,posml_mm_diff,posmr_mm_diff,posrl_mm_diff,posrr_mm_diff;

ros::NodeHandle nh;

//function that will be called when receiving command from host
void handle_cmd (const geometry_msgs::Twist& cmd_vel) {

     demandx = cmd_vel.linear.x;
     demandz = cmd_vel.angular.z;
}

ros::Subscriber<geometry_msgs::Twist> cmd_vel("/cmd_vel", handle_cmd);   //create a subscriber to ROS topic for velocity commands (will execute "handle_cmd" function when receiving data)
mybot::encoderMsgStamped pos_msg;                                //create a "pos_msg" ROS message
ros::Publisher pos_pub("encoderPos", &pos_msg);                          //create a publisher to ROS topic "encoderPos" using the "pos_msg" type

void setup() {
  nh.initNode();                            //init ROS node
  nh.getHardware()->setBaud(115200);         //set baud for ROS serial communication
  nh.subscribe(cmd_vel);                    //suscribe to ROS topic for velocity commands
  nh.advertise(pos_pub);                  //prepare to publish speed in ROS topic
  odrive_serial1.begin(115200);
  odrive_serial2.begin(115200);
  odrive_serial3.begin(115200);
  odrive1.SetVelocity(0,0);
  odrive1.SetVelocity(1,0);
  odrive2.SetVelocity(0,0);
  odrive2.SetVelocity(1,0);
  odrive3.SetVelocity(0,0);
  odrive3.SetVelocity(1,0);
  odrive1.SetPosition(0,0.0);
  odrive1.SetPosition(1,0.0);
  odrive2.SetPosition(0,0.0);
  odrive2.SetPosition(1,0.0);
  odrive3.SetPosition(0,0.0);
  odrive3.SetPosition(1,0.0);
  Serial.begin(115200);
  while (!Serial) ;

}

//_________________________________________________________________________

void loop() {
  nh.spinOnce();
  currentMillis = millis();
  if (currentMillis - previousMillis >= loopTime) {  // run a loop every 100ms
     previousMillis = currentMillis;          // reset the clock to time it
     float modifier_lin = 1.03;        // scaling factor because the wheels are squashy / there is wheel slip etc.
     float modifier_ang = 0.92;        // scaling factor because the wheels are squashy / there is wheel slip etc.

     forward0 = demandx * 1.927982351202 * modifier_lin ; // convert m/s into counts/s
     forward1 = demandx * 1.927982351202 * modifier_lin; // convert m/s into counts/s
     turn0 = demandz * 0.46271576428  * modifier_ang;    // convert rads/s into counts/s
     turn1 = demandz * 0.46271576428 * modifier_ang;    // convert rads/s into counts/s

     forward1 = forward1*-1;      // one motor and encoder is mounted facing the other way
     odrive1.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
     odrive1.SetVelocity(0, forward1 + turn1);
     odrive2.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
     odrive2.SetVelocity(0, forward1 + turn1);
     odrive3.SetVelocity(1, forward0 + turn0); //-1 the motors are on opposite direction
     odrive3.SetVelocity(0, forward1 + turn1);

    // get positions from ODrive
    posfr = odrive3.GetPosition(1) *-1;
    posfl = odrive3.GetPosition(0);

    posmr = odrive2.GetPosition(1) *-1;
    posml = odrive2.GetPosition(0);

    posrr = odrive1.GetPosition(1) *-1;
    posrl = odrive1.GetPosition(0);

    // work out the difference on each loop, and bookmark the old value
    posfl_diff = posfl - posfl_old;
    posfr_diff = posfr - posfr_old;
    posfl_old = posfl;
    posfr_old = posfr;

    posml_diff = posml - posml_old;
    posmr_diff = posmr - posmr_old;
    posml_old = posml;
    posmr_old = posmr;

    posrl_diff = posrl - posrl_old;
    posrr_diff = posrr - posrr_old;
    posrl_old = posrl;
    posrr_old = posrr;

    // calc mm from encoder counts
    posfl_mm_diff = posfl_diff /0.1735184116;
    posfr_mm_diff = posfr_diff /0.1735184116;

    posml_mm_diff = posml_diff /0.1735184116;
    posmr_mm_diff = posmr_diff /0.1735184116;

    posrl_mm_diff = posrl_diff /0.1735184116;
    posrr_mm_diff = posrr_diff /0.1735184116;

     publishPos();
  }
 }

void publishPos() {
  pos_msg.header.stamp = nh.now();      //timestamp for odometry data
  pos_msg.fl = posfl_mm_diff;
  pos_msg.ml = posml_mm_diff;
  pos_msg.rl = posrl_mm_diff;
  pos_msg.fr = posfr_mm_diff;
  pos_msg.mr = posmr_mm_diff;
  pos_msg.rr = posrr_mm_diff;
  pos_pub.publish(&pos_msg);

}

Note: With usual publish and subscribe msgs and the following Arduino/libraries/Rosserial_Arduino_Library/src/ros.h everything works fine for both publishing and subscribing:
 #elif defined(__AVR_ATmega2560__)
 typedef NodeHandle_<ArduinoHardware, 15, 15, 512, 512,FlashReadOutBuffer_>  NodeHandle;

What is it that's actually responsible for producing the Creation of subscriber failed message?

write a simple sketch that publishes one fixed message

For what it's worth, avr-gcc implements its double type as a single precision, 32-bit float.  This may be a problem for your use of float64, irrespective of whatever problem you're encountering now.


text:
Setting float to two decimal places
I'm trying to set my temperature measurements to two decimal places. Currently what I get are six decimal places.
Here is my code:
#include "math.h"

...

(in loop)
temp1 = sensors.getTempCByIndex(0);
     temp1 = roundf(temp1*100)/100;

Once I push temp1 to Firebase realtime database there are sic decimals, such as 26.059999. I'm using dsb20 sensor for temperature measurements.
What could be wrong?
Thanks for your help in advance!

Is temp1 a float or a double? How do you transmit it to Firebase?

@EdgarBonet temp1 is defined as a float. This is how I am pushing it to Firebase (using the esp32Firebase library:   arr.set("/[0]", temp1);     arr.set("/[1]", tms);     Firebase.push(firebaseData2, "Devices/602", arr)

Did you try using a double?

In addition to Majenkos answer:
A float cannot take any decimal number. It has a limited change and a limited resolution in that range you could say. So if often happens, that the flat (rounded) value is not a valid float. This is the case for 26.05. There is no valid float value, that is exactly 26.05. So the nearest valid float value is chosen. The following code would always print 26.059999:
float i = 26.05;
Serial.println(i);

since the variable i contains the float number 26.059999 (nearest valid float value to 26.06). That is the reason, why mostly the rounding of floats is only done directly with the outputting/printing. In that stage the number is not longer bound to the limitations of the float type (since it is internally not again saved in that type).

Thanks for your reply. The problem is that I need to use the number for further calculations and also to push it to Firebase Realtime Database. Therefore, is there a similar solution without serial print?

As Majenko wrote you can use the int datatype. But it is unclear to me, why you really need to reduce to 2 decimal places in your database. If you are doing further calculations with that data the extra digits will not hurt. Or are you then just displaying that data form the database? Then the best way would be to round in that displaying program. Or you could send the data to firebase as a string. Then you can do the same rounding as with Serial.print() while constructing the string. Though I don't see the use in that.

float variables don't have a number of decimal places: that's how they get their name: "floating point" - the decimal point floats around as needed.
It's only when you output the value that it's rendered with a fixed (or limited) number of decimal places.  Using Serial.print() the second digit is the number of decimal points:
Serial.println(temp1, 6); // 26.059999
Serial.println(temp1, 2); // 26.06

Thanks for your reply @Majenko. The problem is that I need to use the number for further calculations and also to push it to Firebase Realtime Database. Therefore, is there a similar solution without serial print?

Use an integer but work with a multiple of your value. For two decimal places multiply it by 100, store it in an integer. When you then want to print it divide it by 100 again.

This is my code, but it still doesn't work:    float temp2 = sensors.getTempCByIndex(0);  int temp3 = roundf(temp2*100);  float temp1 = temp1/100;.

one can convert to n decimals with the String Class
float num = 3.14159
String str1 = String(num, 1) // 3.1
String str2 = String(num, 2) // 3.14
String str3 = String(num, 3) // 3.141


text:
How to let Stepper motor spin constantly?
When i run the code on the Arduino the Stepper only does a small turn every cycle. How can i make that constantly turning?
 #include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position
//Servo Teil
#include <Stepper.h>

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(105);
  // initialize the serial port:
  Serial.begin(9600);
  //Servo
    myservo.attach(3);  // attaches the servo on pin 9 to the servo object
    //Servo

}

void loop() {
  // step one revolution  in one direction:
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);
  //Servo
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  //Servo

}

Does the stepper motor work correctly, when you try it with one of the libraries examples? With your current code the stepper motor should do one revolution (200 steps) per loop() iteration (stopping after the 200 steps, then the servos moves and then the stepper starts again in the next iteration).

rewrite the loop() code ... get rid of the for statements ... refer to the example sketch blinkWithoutDelay for a way to run code at an interval .... every 15 ms move the stepper, then move the servo ... increment/decrement pos accordingly

Yes it does as you say chrisl. Thx jsotola will try it.

You don't "let" a stepper rotate, to get it to move you have to actively step it. When you're not stepping it it stops.

create N square waves, where N is the number of phases in your stepper motor. Make sure the N square waves are appropriately out of phase with one another. Connect amplified versions of the square waves to the stepper motor. The motor will rotate continuously, at a speed determined by the frequency of the square waves.


text:
Error Outputting Values Arduino Serial.print
I am experimenting with the following program I found online (with slight modifications):
int x;
void setup() {
 Serial.begin(9600);
 Serial.setTimeout(1);
}
void loop() {
 while (!Serial.available());
 x = Serial.readString().toInt();
 int y = x + 1;
 Serial.print(y);
}

I am encountering an error in Serial monitor output; if I input 1, I get 21 printed. I think what's happening is that every digit in a number gets incremented by 1, and then 1 is put at the end for some reason. For example, if I input 234, my output is 3451. I think the error lies with the line  x = Serial.readString().toInt();, but am unsure how to fix this. Thank you!

Why such a short timeout?

@EdgarBonet thank you for pointing this out! I'm not sure why the tutorial did this, but changing the timeout to 100 ms seems to fix this error!

There's two problems here.
First, you don't enter "234", you enter "2" followed by "3" and finally "4". Your really small timeout doesn't give the digits enough time to arrive.
Second, your line ending is being received and interpreted as "not a number" which is returned as 0 by .toInt().
What you need to do is:

Don't set a short timeout - you can remove that line entirely.
Use .readStringUntil('\n') to read up until your line ending in one go.

This worked, thank you for explaining everything too! If I remove the timeout entirely, there is notable input lag, so I just increased timeout to 100. Is there any downside to doing this?

Yes, you get a lag. Use the readStringUntil('\n') and the timeout is not used, so you get no lag.

Thanks - tried it and it works awesome.


text:
Slow USB reading operation
I got an Arduino UNO today, and I am just writing a basic blink program. I have 3 LEDS on the arduino. Those LEDS are connected to Pin 1, 2, and 3.
Now I can control those LED by writing octal values 0 to 7 to the /dev/ttyUSB0.
The code I have written so far is:
# pragma GCC optimize ("Ofast")

# define LED1 1
# define LED2 2
# define LED3 3

char buf[4] ;
unsigned char inp, len ;

void setup() {
    pinMode(LED1, OUTPUT) ;
    pinMode(LED2, OUTPUT) ;
    pinMode(LED3, OUTPUT) ;

    Serial.begin(9600) ;
}

void loop() {
    len = Serial.readBytes(buf, 3) ;

    if (len) {
        buf[3] = '\0' ;
        inp = atoi(buf) ;

        // Illuminate LEDs
        digitalWrite(LED1, 1 & inp ? HIGH : LOW) ;
        digitalWrite(LED2, 2 & inp ? HIGH : LOW) ;
        digitalWrite(LED3, 4 & inp ? HIGH : LOW) ;
    }
}

So when I write:

0 turns off all the LEDS
1 turns on LED on pin 1
2 turns on LED on pin 2
3 turns on LED on pin 1 and 2
4 turns on LED on pin 3
5 turns on LED on pin 1 and 3
6 turns on LED on pin 2 and 3
7 turns on all the LEDS.

The problem is that, when I write 7 for example, it takes up to 1 second to turn on the LEDS. If I write 0, it takes another second to turn off the LEDS.
Is there way to control the LEDS in close to real-time?

When sending multiple bytes which together form a single message it is best to use a delimiter character and read the data until there. That way you don't run into timeouts and you can be sure, that the received data represents a full message.
In the cases where the LEDs need 1s to react you are most likely sending less than 3 bytes, which causes the Serial.readBytes() function to time out after the default 1s. I guess you are currently always sending only 1 byte (though you are trying to read 3 byte in your code).
To use a delimiter character there are multiple ways. The easiest fix would be using Serial.readStringUntil('\n'). The newline character (which I used as a parameter here) is a common delimiter character. You would then need to aways send the newline character at the end of a full message.
Just setting the timeout very low is not a very good solution. With a low baudrate as 9600 that can easily mean, that the message is chopped up into multiple parts, because the transmission takes longer than the timeout.

Besides that: I don't really understand, why you need to receive 3 bytes for turning on or off 3 LEDs. One byte (even, when you are just using single digits) has a big enough data space for more than these 3 LEDs. Also you are not really using octal numbers. atoi() is expecting a string representation of a decimal number. There is nothing octal in your code. And then you are using the first 3 bits of the resulting number for controlling the LEDs.
All in all this seems quite complicated for a very basic task. Maybe there is some reason for that, which you didn't write about.

You're calling Serial.readBytes() when there may or may not be 3 bytes available. If there aren't 3, the call waits for them to arrive or for a timeout. That's the delay you are seeing.
If you really want 3 bytes at a time, check whether there are 3 before you try to read them:
if( Serial.available >= 3 )
   len = Serial.readBytes(buf, 3);

When the if fails - because there aren't three bytes available - you won't waste any time waiting for them.

On the Arduino UNO pins 0 and 1 are used for serial communications.  That might not make a difference here, but it's probably a good idea to avoid them unless really needed.

This should be a comment


text:
TTGO TS I²C adress
I'm working on a project using TTGO TS wich communicate wih arduino via I²C protocole
How can I find the adress of TTGO TS board used in I²C communication ?

you would find out the address by reading the instruction manual, or the datasheet

You could also use an I2C scanner (google it, there are dozens of them out there).

The TTGO TS uses an ST7735 display. This is not an I2C device. Instead it uses its own custom serial protocol. Since the DC pin is broken out for you it uses the 4-wire serial interface which is simplest to use with SPI.
It's confusing that they use the terms SCL and SDA, which makes you think it's I2C, but it's not.

Like @romkey said, use a I²C scanner to find the address of the device, for example this one from the Arduino website. Connect the device to the Arduino board, upload the code and look up the I²C address of your device.


text:
Turn off Timer1 / Timer1 One-shot
A zero detector crossover sends a pulse to the Arduino, it must start counting x time and then a pulse is sent from the Arduino, once the timer reaches time x, it must stop counting and only start counting again when it receives the new pulse of the zero crossing detector, the idea is to do something like this:

What I don't know is how to keep the timer off all the time toff that appears in the image.

A zero detector crossover sends a pulse to the arduino... How does your code and wiring detect the zero cross-over now? Is the detector external and just sends a signal to Arduino? Wouldn't you just reset the timer any time you detected the cross-over to positive? Or doesn't the detector distinguish between a positive crossing and a negative one? Or are you really wanting to know how to do a cross-over detection for a sinusoidal signal?

@lurker what I get from the zero crossing detector is a train of pulses, which varies from 0 to 5v each time it passes through zero, but that's not the point, create an edge ISR when the signal varies, at that time it should start the counting, stop when it reaches the time x that I need and stay off until the next zero edge, in the examples that I have seen the timer restarts and continues counting, I need it to turn off or stop counting until the next zero crossing

Does this answer your question? Fan regulator control from Arduino

You can trick the timer into doing one-shot, by setting the counter to a value higher than TOP. See https://hackaday.com/2015/03/24/avr-hardware-timer-tricked-into-one-shot/

the way to turn off the Timer is to set the CS12, CS11 and CS10 prescale bits to 0, in this way the CLK signal is disconnected and the timer stops counting, when you want the timer to continue counting, they are set back to 1 the CS12, CS11 and CS10 bits according to the selected prescale.
byte savePrescale

savePrescale = TCCR1B & (0b111<<CS10);
...
TCCR1B &= ~(0b111<<CS10); // Stop Timer1 Clock
...
TCCR1B |= savePrescale;  // Restart Timer1 clock.
...

You can initiate a "One shot" timer at each zero-crossing.
The trick @Gerben mentioned in turn off Timer1 / Timer1 One-shot eventually links to code at https://github.com/bigjosh/TimerShot which does the one-shot functionality on Timer2 by idling the timer at TCNT2=0 with OCR2A=0, and using the TCNT2 space above 0 to operate an adjustable oneshot on OC2B.
This trick can be adapted to Timer1:
// The one shot pulses are output on Digital pin OC1B (Arduino Uno D10, Mega D12, Nano D3)
// Modified by Dave Forrest 2020-01-11 for Timer 1
// Based on Josh Levine's Nov 23, 2015 work at https://github.com/bigjosh/TimerShot/blob/master/TimerShot.ino

#define OSP_SET_WIDTH(cycles) (OCR1B = 0xffff-(cycles-1))

// Setup the one-shot pulse generator and initialize with a pulse width that is (cycles) clock counts long

void osp_setup(uint16_t cycles) {

  TCCR1B =  0;      // Halt counter by setting clock select bits to 0 (No clock source).
              // This keeps anything from happeneing while we get set up

  TCNT1 = 0x00;     // Start counting at bottom.
  OCR1A = 0;      // Set TOP to 0. This effectively keeps us from counting because the counter just keeps reseting back to 0.
          // We break out of this by manually setting the TCNT higher than 0, in which case it will count all the way up to MAX and then overflow back to 0 and get locked up again.
  OSP_SET_WIDTH(cycles);    // This also makes new OCR values get loaded from the buffer on every clock cycle.

  TCCR1A = 0b11<<COM1B0  | 0b11<<WGM10;  // OC1B=Set on Match, clear on BOTTOM. Mode 15 Fast PWM.
  TCCR1B = (0b11<<WGM12)| (0b001<<CS10); // Start counting now. WGM 15=0b1111  to select Fast PWM mode

  //DDRB |= _BV(2);     // Set pin to output (Note that OC1B = GPIO port PB2 = Arduino Uno Digital Pin 10)
  DDRB |= _BV(6);     // Set pin to output (Note that OC1B = GPIO port PB6 = Arduino Mega Digital Pin 12)
  //DDRD |= _BV(3);     // Set pin to output (Note that OC1B = GPIO port PD3 = Arduino Nano Digital Pin 3)
}

// Setup the one-shot pulse generator

void osp_setup() {
  osp_setup(1);
}

// Fire a one-shot pulse. Use the most recently set width.

#define OSP_FIRE() (TCNT1 = OCR1B - 1)

// Test there is currently a pulse still in progress

#define OSP_INPROGRESS() (TCNT1>0)

// Fire a one-shot pulse with the specified width.
// Order of operations in calculating m must avoid overflow of the uint16_t.
// TCNT2 starts one count lower than the match value becuase the chip will block any compare on the cycle after setting a TCNT.

#define OSP_SET_AND_FIRE(cycles) {uint16_t m=0xffff-(cycles-1); OCR1B=m;TCNT1 =m-1;}

void setup()
{
  osp_setup();

}

void loop()
{
  // Step though 0-11 cycle long pulses for demo purposes
  for (uint8_t o = 0; o < 101; o++) {
    OSP_SET_AND_FIRE(o);
    while (OSP_INPROGRESS());         // This just shows how you would wait if necessary - not necessary in this application.
    //_delay_us(1);      // Wait to let the audience clap
  }
}

This code produced pulses with a resolution of 62.5ns, which is on the edge of what my test equipment can measure.  Here's a 6.25us, 100 cycle pulse next to a 1 cycle pulse:

With Timer1's 16 bit range and the /1 prescaler you can do pulses from 62.5ns to 4us.  With the /1024 prescaler, (TCCR1B|=(0b101 <<CS10);) it can do 64us up to 4.194sec.  With /256 prescaler, (TCCR1B|=(0b100 <<CS10);) it can do 16us up to 1.05sec.
For a one shot triggered on a zero-crossing, you might try something like this with the above
void loop()
{
  ...
  int t1_us = 1000000UL/60 /8 ; // 1/8th of a 60Hz cycle

  if(needOneShot){  // Set needOneShot with an interrupt or sensor or something
    OSP_SET_AND_FIRE(t1_us/16);  // 16us ticks with the /256 prescaler
     needOneShot = false;
  }
  ...
}


text:
Arduino pro mini resetting itself
I am working on a brushed motor quadcopter using Arduino pro mini.
Every time I try to throttle, the Arduino gets reset by itself (motors start to spin but they will be turned off in 2 sec). I have added a 1000uf capacitor (tried up to 3300uf) to the input of Arduino VCC and GND. But still having the same issue.

Please show a wiring diagram or schematic of your setup

Do you have suppression capacitors on your motors?

What battery are you using?

I am using 3.7V 650mAH (Lithium Polymer) Lipo Rechargeable Battery for Drone.
Specifications
Battery model: KP 802540
Nominal voltage: 3.7V
Charging voltage: 4.2V
Nominal capacity: 650mAh
Operating temperature: -10 to 55°C
Discharging cut-off voltage: 3.2V
Charging current: 1C (max)
Discharge current: 15C (max)
Dimension: 43mm(L) x 25mm(W) x 8mm(H)
Weight: 10g..

and iam using 8520 Colorless Motor

@chrisl i have added schematic

Sounds like a power issue. Are you using the same battery for the motors and Arduino? If yes, Can you try a different battery/power source for arduino?

Yes I am using the same battery.

Now Iam planning to use 1200mah with 20C discharge current, so that i get 6A (20*1.2 /4) per motor (However my motor 8520 stall current is 5.3A) is that fine?

Before replacing the batteries, You can try a different battery just for Arduino and see if it still resets. Because more batteries = more weight.

I have also tried to connecting directly to computer(without battery) while calibration..it has resets. @AjithGopi

Can you try replacing the motors with LEDs and check if it resets? If it works, only connect one motor at first and see what happens.

Let us continue this discussion in chat.


text:
AJ-SR04M Screw Purpose
I've got 3 AJ-SR04M sensors working on an Arduino MKR Wifi 1010, but I was curious what the purpose of this screw on the sensor boards is. It seems to somehow impact the accuracy/performance, but I can't seem to find any info on it. Anyone know what this is called/what it does exactly?

Adjustable inductor

could be a selector switch

@jsotola No, it's an adjustable inductor. You get them by the hundred in old radios. The black thing in the middle is a ferrite core that screws in and out to change the inductance. You need a special plastic screwdriver to adjust them so that the metal of the screwdriver doesn't affect the inductance while you're tuning it.

The purpose is probably to tune a bandpass filter. At a guess.

As @Majenko says, it's probably for inductor tuning. Since it's not mentioned in the documentation, I would suppose it may already be tuned or adjusted at the factory during final test. That's not the say you can't tinker with it, but as you noted, it requires a little more detail on what it exactly does to do that.

@Majenko thank you! Luckily I only fiddle with one of 3 that I bought so I'm just going to try to tune it back to look like the other 2.


text:
SIM808 Doesn't detect SMS if sent while offline
I'm running UNV SIM808 Shield with Arduino Uno using DFRobot_SIM808. The shield has no issues detecting incoming SMS while powered on. I just found out if the shield is off while sending the SMS, it won't detect it when it becomes online again.
#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>

#define MESSAGE_LENGTH 160
char message[MESSAGE_LENGTH];
int messageIndex = 0;

char phone[16];
char datetime[24];

#define PIN_TX    3
#define PIN_RX    2

SoftwareSerial mySerial(PIN_TX,PIN_RX);
DFRobot_SIM808 sim808(&mySerial);//Connect RX,TX,PWR,

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

  //******** Initialize sim808 module *************
   while(!sim808.init())  { Serial.println("Starting Sim808...");   sim808.powerUpDown(9); }

  delay(3000);
  Serial.println("Init Success, please send SMS message to me!");
}

void loop() {
  //*********** Detecting unread SMS ************************
   messageIndex = sim808.isSMSunread();
    Serial.print("messageIndex: ");
    Serial.println(messageIndex);

   //*********** At least, there is one UNREAD SMS ***********
   if (messageIndex > 0) {
      sim808.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime);

      //***********In order not to full SIM Memory, is better to delete it**********
      sim808.deleteSMS(messageIndex);
      Serial.print("From number: ");
      Serial.println(phone);
      Serial.print("Datetime: ");
      Serial.println(datetime);
      Serial.print("Recieved Message: ");
      Serial.println(message);
   }
}

I'm sharing the serial monitor data after powering off the shield. I sent a this message (2:24) at 2:24 AM local time. 10 mins later, I powered the shield on and waited for the message to be detected but with no luck for 15 mins. I sent another message (2:49) local time while the shield is on and it was detected right away along with the previous message.

It runs every 3 seconds but I cleaned the data

02:34:56.342 -> Starting Sim808...
02:35:06.958 -> Init Success, please send SMS message to me!
02:35:09.602 -> messageIndex: -1
02:40:00.686 -> messageIndex: 0
02:45:02.311 -> messageIndex: 0
02:49:26.940 -> messageIndex: 0
02:49:29.560 -> messageIndex: 0
02:49:32.216 -> messageIndex: 0
02:49:33.565 -> messageIndex: 7
02:49:36.269 -> From number: +***********
02:49:36.322 -> Datetime: 21/04/21,02:24:20+12
02:49:36.369 -> Recieved Message: 2:24
02:49:37.624 -> messageIndex: 8
02:49:40.373 -> From number: +***********
02:49:40.373 -> Datetime: 21/04/21,02:49:28+12
02:49:40.426 -> Recieved Message: 2:49
02:49:43.029 -> messageIndex: 0
02:49:45.691 -> messageIndex: 0
02:49:48.314 -> messageIndex: 0

Here is code for sim808.isSMSunread(); function. Maybe there is something can be tweaked within the code can mitigate this issue:
char DFRobot_SIM808::isSMSunread(){
    char gprsBuffer[48];  //48 is enough to see +CMGL:
    char *s;

    sim808_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD);    delay(1000);
    sim808_send_cmd(F("AT+CMGL=\"REC UNREAD\",1\r\n"));
    sim808_clean_buffer(gprsBuffer,31);
    sim808_read_buffer(gprsBuffer,30,DEFAULT_TIMEOUT);

    if(NULL != ( s = strstr(gprsBuffer,"OK"))) {
        delay(50);
        return 0;
    } else {
        sim808_wait_for_resp("OK\r\n", CMD);
        sim808_send_cmd("AT+CMGL=\"REC UNREAD\",1\r\n");
        sim808_clean_buffer(gprsBuffer,48);
        sim808_read_buffer(gprsBuffer,47,DEFAULT_TIMEOUT);
        if(NULL != ( s = strstr(gprsBuffer,"+CMGL:"))) {
            s = strstr(gprsBuffer,":");
            if (s != NULL) {
                sim808_wait_for_resp("OK\r\n", CMD);
                return atoi(s+1);
            }
        } else {
            return -1;
        }
    }
    return -1;
}

What i'm looking for is to make the shield detect any unread messages if it was sent while off?

you will have to build a time machine

sounds like your provider does not store SMS messages and transmits when your device comes online ... test it with your cell phone ... turn off your phone and send SMS to your phone .... then turn on your phone

@jsotola Once I put the sim in my phone, I got the SMS immediately.

then you need to learn how the phone retrieves stored messages ... it has nothing to do with the arduino

do the sim808 have at commands like in this page https://www.developershome.com/sms/readSmsByAtCommands.asp ?

@user30878 I'm not quiet sure if I understood you, but yes the module is responding to AT commands and this how to it works.

Check the page I'm linking to.

@user30878, as I understand it, they're having problems retrieving messages that were queued on the network after having just powered up; not problems with reading messages generally.

@timemage the command "CMGR" is said to receive SMS from storage area. I don't know what the storage is, but the comments above said it might be the solution.

this question is worth a look https://stackoverflow.com/questions/29867646/minicom-atcmgr-n-not-showing-the-sms-content   the URL given in the answer has the details about storage https://www.smssolutions.net/tutorials/gsm/receivesmsat/

@user30878 I tried all possible storage types but end up with the same issue. AT+CPMS="SM" and then ME, MT, SM_P, ME_P and MT


text:
Arduino simulator - generating sine wave from PWD (Oscilloscope read is rectangular)
trying to create this simple circuit where a rectangular voltage input is transferred to a sine wave output.
the process is quite simple, but I couldn't see the actual sine wave when connecting an oscilloscope.
I'm currently working on a simulator online, so I thought it would be best to share the circuit with the c++ code, and perhaps you would have any insights on why I keep seeing rectangular output voltage rather than sine when the data is indeed a sine wave:
here's an image of the circuit for some specific time:

and the code that generates the sine wave is
#include <math.h>

const int numSamples = 500;
const float pi = 3.1415;
int f = 2; // signal frequency
float sf = 500.0; // sample frequency > 2*f (Nyquist)
int sineSignal[numSamples];

void setup(){
    pinMode(13, OUTPUT);
    // creating sine signal:
    for (int i = 0; i < numSamples; i++){
        float t = i / sf;
        // +1 shift to get values from 0 to 2
        sineSignal[i] = (int) (127 * (sin(2 * pi * f * t) + 1.0));
    }
}

void loop(){
    int pinToConnect = 9;
    for (int i = 0; i < numSamples; i++){
        analogWrite(pinToConnect, sineSignal[i]);
        delay(2);
    }
}

ps. this is all based on this video: How to Generate Sine Wave using Arduino?

It's working as intened.
The arduino UNO has no DAC (digital to analog converter) onboard, so all it can produce are digital signals, either 0 or 5v. The analogWrite function uses Pulse Width Modulation to produce an output that, on average, has the requested voltage, by quickly alternating between logic low and high with different durations.
This is done at the hardware level using the Atmega's timers, and it's very useful in driving LEDs, servos, steppers and more, but it doesn't produce a steady analog output.
I would suggest either moving to a chip that has an onboard DAC, using an external DAC chip such as this one, or building a simple DAC yourself.
An even simpler solution would be building a RC lowpass filter on the output pin, which would provide a simple, but probably imprecise, way to smooth out the signal and make it look like an analog one

Thank you for the comment - just a few clarifications: the led light does oscillate as expected (According to a sine wave), but the oscilloscope does not display that. what is the reason for that?

The light you see from the LED is averaged out by your eye, which can't really see the frequencies in the hundreds of Hz used by Arduino's PWM. The oscilloscope, on the other hand, is triggered on rising/trailing edges and has a much higher resolution, so it will show more details at high frequency. Hypothetically, if you filmed the LED in slow motion, you would be able to see it turn on and off repeatedly