text:
Asymmetric encryption on a Teensy?
I want to monitor an input and then send the information in an encrypted way that can't be easily unlocked even if a malicious actor gets access to the device itself. I'm new to using the Teensy although I have done a few simple things with Arduino microcontrollers. I was hoping to find out if anyone has implemented RSA or other asymmetrical encryption on a Teensy or to figure out if it has enough processing power to make it feasible. I would also accept using other Arduinos (I have an MKR1000 as well), for this but I assume because the Teensy has much better performance it's more likely to be able to do computationally expensive encryption.
This won't need to decrypt anything, it will only be sending data encrypted using the public key of the receiving user.

Your question can not be fully answered, because we don't know how many bytes per second you intend to encrypt. You should already be aware that asym. encryption methods like RSA only exchange symetric keys with asymetric technology. The pyload is en-/decrypted synchronous. If the hacker get's access to your device, the security depends on whether you have secured the private key with a password, and how secure the password is. 100% security is impossible. The internet is full of infos on teensy encryption, e.g.: https://forum.pjrc.com/threads/24327-RSA-encryption

I'm not able to access that site due to my VPN and archive.is appears to have the same issue. Can you share the relevant information here? I don't expect a black and white yes/no answer, I would accept info on encryption methods and/or how many bytes per second RSA encryption a Teensy is likely to be capable of.

I have not given you an answer you can accept. I just mentioned, that you give us too few information to answer the question "Is the teensy fast enough" and I pointed you to an page where the usage of an RSA lib  is explained. Please do not excpect me to write a complete program or library you can use, I have neither the time nor the intention to do so in my rare spare time. If you can access SO pages, why can't you access ordinary internet pages?

The site you've linked has blocked my VPN or IP addresses from my country, it seems. I am sorry. I would also be very surprised if anyone went to the trouble to write a library as a response to this question. Maybe I was unclear in wording, I meant I would accept answers that explain how to determine the speed of the encryption on the Teensy.

I'm sorry too, if it looked like I tried to offend or attack you. That was not my intention. The best way to determine the speed  of an crypt method is to use some libs and check wheter it works and how many through put one can archieve. The speed and RAM consumption  heavily depends on the algorithm that is used. So asynchronous encryption is very time consuming, but as I mentioned, it is mainly used to encrypt synchrounous keys. And synchronous en-/decryption is much more performant. But without having to chance to download a lib, I fear you have no chance to try out something.

A Hint: Try the following keywords in a search engine: RSA, Teensy, Relic. Probably you have access to the Relic project on GIT hub .  https://github.com/relic-toolkit/relic . Here is an older page: https://code.google.com/archive/p/relic-toolkit/

I'm a bit confused about your use of the word asynchronous. I'm not very familiar with cryptography so I don't know anything about synchronous vs asynchronous encryption, this isn't terminology I've heard used for encryption before. Did you mean asymmetric or is synchronicity something I need to look into?

@PeterPaulKiefer thank you for linking the relic toolkit. I will investigate. I'm concerned about the disclaimer on it "RELIC is at most alpha-quality software. Implementations may not be correct or secure and may include patented algorithms. There are many configuration options which make the library horribly insecure." I guess I assumed there would be something PGP-like out there for Arduinos... maybe it doesn't exist?

I fear you can not write a really good encryption for your project, if you do not learn how encryption works. That's nothing one can teach you here. Check the internet for information on synchronous, asynchronous,  encryption, RSA, DSA, Diffie Hellmann, Public key, Private Key. Then you understand the issue with the relic toolkit better and can decide if it is useful.

Synchronous encryption means you have only one key both endpoint must know. This key is used to encrypt and to decrypt a payload. The synchrounous methods are very performant compared to the asynchronous methods. Asynchrounous means you have two keys a public and a private key. You send the public key to the communication partner which uses it to encrypt a payload and then sends the encrypted payload to you. Only the private key can be used to decrypt the payload, but the public key can not be used for decryption.

I think we need to back up here and look at the big picture.  You say you want a system that can't easily be unlocked even if an assailant has the hardware itself.  But then he'd have access to the raw sensor output directly, and wouldn't even need to worry about any encryption.  Is there something I'm missing here?

@Boggyman An attacker would naturally have raw sensor data from the point of getting control of the system onward. But I would like for the attacker to not be able to decrypt data that was sent prior to obtaining the hardware, even if the attacker had somehow recorded it.

Teensy4.1 has 55 digital IO (serial) pins at up to 200MHz. The USB port supports 480mbps, and ethernet is 10/100mbps. You're limited to 32 DMA channels, though (complicated but these are used to access onboard peripherals/memory). You don't have much contiguous ram, either.
Now, you haven't explained what you're doing with this data. This matters because even though the CPU is running at 600MHz, asymmetric encryption is slow. Are you trying to perform real-time encrypted communication? Are you just sending or receiving data as well?
Nothing stopping you from asymmetrically encrypting on a Teensy. You can find the source code for the OpenSSL functions RSA_public_encrypt and RSA_private_decrypt.
This question goes into calculating how many CPU cycles are needed to encrypt X bytes of data.
However, asymmetric encryption has problems: Like I said, it's slow - specifically RSA, and the size of the data you can encrypt depends on the size of your key and padding.
If you want to communicate in something resembling real-time, you want to use hybrid encryption. You should read about how TLS works; the short version is that an asymmetric handshake occurs where the two parties agree on a symmetric key. Once you decide what your data actually is, you can quantize it (eg. TLS 'chunks' are up to 16KB which are then sent as multiple TCP packets) then both parties use the symmetric key to send/receive - which can encrypt large data chunks without issue.


text:
Always HIGHT line on Oscilloscope when UNO's Fast PWM TOP ICR1
I have been trying to get an answer my question for a 2 days already. It's good for knowledge collecting and playing with different things, but there haven't been a solution so far.
I'm trying to leverage the HXT500 Servo with the Fast PWM with a TOP ICR1
I'm using the DFRobot DFRduino UNO v3.0 (R3) analog of the Arduino UNO. Based on the Atmega 328P-PU
I have an Oscilloscope till 5 MHz as additional tool
Question

Why the Fast PWM, TOP ISC1 always has the HIGHT only on a oscilloscope
Why the Clock Prescaler doesn't work

My investigations & observations
I activated the PWM with TOP ICR1 but on my oscilloscope showed only a 5V straight line, I checked different diapasons (horizontal bases) (1a). Connected to pins 10 or 9. I assumed that my UNO works on 1 MHz (9.2.1 Default Clock Source on Page 37) and calculated ICR1, OCR1A:B for 0 and 180 degree.
     void setup() {
      // all as Ports (for outputs)
        DDRB=0xFF;
        DDRC=0xFF;
        DDRD=0xFF;

      // Table 16-4 on Page 141
      // Fast PWM TOP is ICR1
      TCCR1A|=(0<<WGM10)|(1<<WGM11);
      TCCR1B|=(1<<WGM13)|(1<<WGM12);
      ICR1=2499;

      // Table 16-2 on Page 140
      // Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode)
      TCCR1A|=(1<<COM1A1)|(1<<COM1B1);

      // Table 16-5 on Page 143
      // clkI/O/8
      TCCR1B|=(0<<CS12)|(1<<CS11)|(0<<CS10); // (2a)
    }

    void loop() {
      digitalWrite(LED_BUILTIN, HIGH);
        // 90 degree
        OCR1A=299;
        OCR1B=299;
      delay(1000);
      digitalWrite(LED_BUILTIN, LOW);
        // 0 degree
        OCR1A=49;
        OCR1B=49;
      delay(1000);
    }

There I noticed the following issues:

I tried different Prescales - there weren't any differences (2a)
I tried 1 MHz, 8 MHz, 16 MHz - straight HIGHT line

What I have tried next:

To use an Example for Servo leveraging from Arduino IDE. It worked but as I understood it worked via Interrupts, not a Hardware solution
To use Fast PWM, 9 & 10-bit. (2a) Prescales didn't work - I had movement
To use Fast PWM, 8-bit (with code adjustment and wrong angles). (2a) Prescalers didn't work - I had movement

A 5MHz oscilloscope likely can not resolve a 5MHz square wave.  What you may see is a distorted wave closer to a sin wave than a square wave.  You may not see anything but the DC component of higher frequency signals.  I don't know why you only see 5 volts when you are expecting a wave form or voltage less than 5 volts.  There maybe something wrong with the code, hardware, connections or you may have your oscilloscope AC coupled.

@st2000, thanks for your attention and comment
The wave explanation - yes, it makes sense,  I   didn't think in this way, thanks
Considering possible issues: connections - it's fine, because in another modes it works w/o changing these connections
hardware - possible, but I don't know how to check it, but with the Fast AWM 9-bit it works
Interestingly: there is the same/similar issue with Normal, CTC modes
Code - it would be easiest reason )

You might want to set the TCCR1A and TCCR1B registers to 0 before your code as the Arduino library sets the WGM10 bit. Or change the first |= to a =. By leaving the WGM10 bit set, you get fast PWM mode, with TOP set to OCR1A. Combined with your other code, this would result in both pins having a 100% duty cycle.
So use
TCCR1A=(0<<WGM10)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12);

or
TCCR1A=0;
TCCR1B=0;
TCCR1A|=(0<<WGM10)|(1<<WGM11);
TCCR1B|=(1<<WGM13)|(1<<WGM12);

Other than that, you code looks fine, and should give you a 800Hz signal.
PS "I assumed that my UNO works on 1 MHz"; no, the UNO runs at 16Mhz.

thanks. I very appreciate the time that you spent here.
I have tried and it started working, but with some shift, because there were that wrong assumption, that you mentioned, about the System Clock Speed
Currently, the fast PWM TOP ICR1, Prescaler work and the math is matched

source: Stack Exchange

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

sort: votes


text:
Phantom reading
my project is to control led diode and dc motor, test shield buttons, and check system run time.
Testing buttons and run time i have done.
Deal is with led and dc motor control.
I'm getting phantom reading, that means,when i'm scrolling main menu, diode and dc motor starts working, when they shouldn't.
Dc motor or led diode should work only when i enter their control menu, not when i'm in main menu.
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int masterKey = A0;
int keypadKey = 0;
int buttonPress = 0;

char push;

byte menu = 1;
byte menuOld = 1;
byte menuAll = 4;

//_______LED/MOTOR_________________
int speedall;
int mtor = 5,
   led = 6,
   error = 7;
const int Upstep = 3;
const int maxspeed = 255;

void setup() {
 pinMode(led, OUTPUT);
 pinMode(mtor, OUTPUT);
 lcd.begin(16, 2);
 mainMenu();
 delay(100);
 Serial.begin(9600);
}

void loop()
{
 push = readKeypad();
 menuContr();
 if (push == btnSELECT) //enter selected menu
 {
   waitKey();
   switch (menu) {
     case 1:
       lcd.begin(16, 2);
       lcd.setCursor(0, 0);
       lcd.print("Push the buttons");
       ButtonTest();
       break;
     case 2:
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Speed 0 to 255:");
       MotorControl();
       break;
     case 3:
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Brightness 0 to 255:");
       LEDControl();
       break;
     case 4:
       SystemTime();
       break;
   }
   mainMenu();
   waitKey();
 }
 delay(10);
}
//____________________________
void ButtonTest() {
 while (readKeypad() != btnSELECT) {
   lcd.setCursor(9, 1);
   lcd.print(millis() / 1000);
   lcd.setCursor(0, 1);
   int lcd_key = readKeypad();
   switch (lcd_key) {
     case btnRIGHT:
       lcd.print("RIGHT ");
       break;
     case btnLEFT:
       lcd.print("LEFT   ");
       break;
     case btnUP:
       lcd.print("UP    ");
       break;
     case btnDOWN:
       lcd.print("DOWN  ");
       break;
     case btnSELECT:
       lcd.print("SELECT");
       break;
     case btnNONE:
       lcd.print("NONE  ");
       break;
   }
 }
}
//____________________________
void MotorControl() {
 while (readKeypad() !=  btnSELECT) {
   if (readKeypad() == btnUP) {
     speedall <= maxspeed;
     speedall += Upstep;
     lcd.setCursor(5, 2);
     lcd.print("                ");
     lcd.setCursor(5, 2);
     lcd.print(speedall);
     delay(100);
     analogWrite(mtor, speedall);

   }
   else if (readKeypad() == btnDOWN) {
     speedall <= maxspeed;
     speedall -= Upstep;
     Serial.print(speedall);
     lcd.setCursor(5, 2);
     lcd.print("                ");
     lcd.setCursor(5, 2);
     delay(100);
     analogWrite(mtor, speedall);
   }
 }
}
//____________________________
void LEDControl() {

 while (readKeypad() != btnSELECT) {
   if (readKeypad() ==  btnUP) {
     speedall < 255;
     speedall += Upstep;

     lcd.setCursor(5, 2);
     lcd.print("                ");
     lcd.setCursor(5, 2);
     lcd.print(speedall);
     delay(100);
     analogWrite(led, speedall);

   }
   else if (readKeypad() == btnDOWN) {
     speedall > 255;
     speedall -= Upstep;

     lcd.setCursor(5, 2);
     lcd.print("                ");
     lcd.setCursor(5, 2);
     lcd.print(speedall);
     delay(100);
     analogWrite(led, speedall);

   }
 }
}
//____________________________
void SystemTime() {
 lcd.clear();
 while (readKeypad() != btnSELECT) {
   lcd.setCursor(6, 0);
   lcd.print("TIME");
   lcd.setCursor(7, 1);
   lcd.print(millis());
   lcd.print("s");
   delay(100);
   lcd.clear();
 }
}
//______________________________

void mainMenu() {
 lcd.clear();
 lcd.setCursor(0, 0);
 switch (menu) {
   case 1:
     Serial.print(speedall);
     lcd.print("Button test");
     break;
   case 2:
     Serial.print(speedall);
     lcd.print("Motor contr");
     break;
   case 3:
     Serial.print(speedall);
     lcd.print("LED contr");
     break;
   case 4:
     Serial.print(speedall);
     lcd.print("Syst run time");
     break;
 }
}
//____________________________
void executeAction() {
 switch (menu) {
   case 1:
     ButtonTest();
     break;
   case 2:
     MotorControl();
     break;
   case 3:
     LEDControl();
     break;
   case 4:
     SystemTime();
     break;
 }
}
void menuContr() {
 waitKey();
 if (push == btnUP) {
   menu++;
   if (menu > menuAll)
     menu = 1;
 }
 else if (push == btnDOWN) {
   menu--;
   if (menu == 0)
     menu = menuAll;
 }
 if (menu != menuOld) {
   mainMenu();
   menuOld = menu;
 }
}
int readKeypad() {
 keypadKey = analogRead(masterKey);
 if (keypadKey > 1000) return btnNONE;     // about 1023
 if (keypadKey < 50)   return btnRIGHT;    // about 0
 if (keypadKey < 195)  return btnUP;       // about 99
 if (keypadKey < 380)  return btnDOWN;     // about 255
 if (keypadKey < 555)  return btnLEFT;     // about 409
 if (keypadKey < 790)  return btnSELECT;   // about 640
 return btnNONE;
}
void waitKey() {
 while ( analogRead(masterKey) < 800) {}
} ```

what have you done to debug your code? ... i see a few serial.print statements ... use more of them to trace the program flow

yeah, i have used some to track phantom readings. But still can't find where is the problem

please do not make an assumption that the problem is caused by phantom reading ... making such an assumption will hinder you in detecting the actual cause .... please present the sketch with the debugging code included and add the content of the serial monitor to your post

ok, tnx for feedback

a couple of observations ... waitKey() should be named waitKeyRelease() ...... the MotorControl() function does not wait for key to be released ... the UP or DOWN key is still pressed when the function is first executed

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


text:
Wemos d1 mini code not uploading
I have a wemos d1 mini. I uploaded a code in wemos d1 mini and after that my wemos mini not working. I tried to upload another code in it even the led blink sketch and even a blank sketch but whenever I tried to do that it just shows connecting but never connects to Arduino ide.
First of all, whenever I tried to connect it to the computer or power it up, its built-in light stays bright and in the serial monitor, it shows garbage characters continuously. But when I connect GPIO 0(d3) of wemos mini to the ground and press the reset button it starts the boot mode and when I upload any code it shows connecting but never upload any code here's the code which uploaded first in it.
#include <WiFiManager.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <BlynkSimpleEsp8266.h>
BlynkTimer timer;

//Pin assignments
#define switch_1 3 // D5 Pin of NodeMcu
#define switch_2 14 // D6 Pin of NodeMcu
#define switch_3 12 // D7 Pin of NodeMcu
#define switch_4 13
// D0 Pin of NodeMcu
#define button 2
#define relay_1 4 //D1 Pin of NodeMcu
#define relay_2 5 //D2 Pin of NodeMcu
#define relay_3 16 //RX Pin of NodeMcu
#define relay_4 15 //D4 Pin of NodeMcu

#define LED1 1 //D0 Pin of NodeMcu

int MODE = 0;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Android-AP960A";
char pass[] = "talal123";

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "3ueT9aVLvkL60q8piJ6p5Kxx31zZ5xEC";

int switch_1_ON = 1;
int switch_2_ON = 1;
int switch_3_ON = 1;
int switch_4_ON = 1;

BLYNK_WRITE(V1)
{
int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
digitalWrite(relay_1, pinValue); // process received value
}

BLYNK_WRITE(V2)
{
int pinValue = param.asInt(); // assigning incoming value from pin V2 to a variable
digitalWrite(relay_2, pinValue); // process received value
}
BLYNK_WRITE(V3)
{
int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
digitalWrite(relay_3, pinValue); // process received value
}

BLYNK_WRITE(V4)
{
int pinValue = param.asInt(); // assigning incoming value from pin V2 to a variable
digitalWrite(relay_4, pinValue); // process received value
}

void internet() //When this device connects with internet
{
//**************************************
//Switch 1 configuration
//**************************************
if (digitalRead(switch_1) == HIGH)
{
if (switch_1_ON == 0 )
{
digitalWrite(relay_1, LOW);
Blynk.virtualWrite(V1, 0);
switch_1_ON = 1;
}
}

if (digitalRead(switch_1) == LOW )
{
if (switch_1_ON == 1)
{
digitalWrite(relay_1, HIGH);
Blynk.virtualWrite(V1, 1);
switch_1_ON = 0;
}
}
//**************************************
//Switch 2 configuration
//**************************************
if (digitalRead(switch_2) == HIGH)
{
if (switch_2_ON == 0 )
{
digitalWrite(relay_2, LOW);
Blynk.virtualWrite(V2, 0);
switch_2_ON = 1;
}
}

if (digitalRead(switch_2) == LOW )
{
if (switch_2_ON == 1)
{
digitalWrite(relay_2, HIGH);
Blynk.virtualWrite(V2, 1);
switch_2_ON = 0;
}
}
//**************************************
//Switch 3 configuration
//**************************************
if (digitalRead(switch_3) == HIGH)
{
if (switch_3_ON == 0 )
{
digitalWrite(relay_1, LOW);
Blynk.virtualWrite(V3, 0);
switch_3_ON = 1;
}
}

if (digitalRead(switch_3) == LOW )
{
if (switch_3_ON == 1)
{
digitalWrite(relay_3, HIGH);
Blynk.virtualWrite(V3, 1);
switch_3_ON = 0;
}
}
//**************************************
//Switch 4 configuration
//**************************************
if (digitalRead(switch_4) == HIGH)
{
if (switch_4_ON == 0 )
{
digitalWrite(relay_4, LOW);
Blynk.virtualWrite(V4, 0);
switch_4_ON = 1;
}
}

if (digitalRead(switch_4) == LOW )
{
if (switch_4_ON == 1)
{
digitalWrite(relay_4, HIGH);
Blynk.virtualWrite(V4, 1);
switch_4_ON = 0;
}
}
}
//********************************************

void no_internet() //When this device doesn't gets internet
{
//**************************************
//Switch 1 configuration
//**************************************
if (digitalRead(switch_1) == HIGH)
{
if (switch_1_ON == 0 )
{
digitalWrite(relay_1, LOW);
switch_1_ON = 1;
}
}

if (digitalRead(switch_1) == LOW )
{
if (switch_1_ON == 1)
{
digitalWrite(relay_1, HIGH);
switch_1_ON = 0;
}
}
//**************************************
//Switch 2 configuration
//**************************************
if (digitalRead(switch_2) == HIGH)
{
if (switch_2_ON == 0 )
{
digitalWrite(relay_2, LOW);
switch_2_ON = 1;
}
}

if (digitalRead(switch_2) == LOW )
{
if (switch_2_ON == 1)
{
digitalWrite(relay_2, HIGH);
switch_2_ON = 0;
}
}
//**************************************
//Switch 3 configuration
//**************************************
if (digitalRead(switch_3) == HIGH)
{
if (switch_3_ON == 0 )
{
digitalWrite(relay_1, LOW);
switch_3_ON = 1;
}
}

if (digitalRead(switch_3) == LOW )
{
if (switch_3_ON == 1)
{
digitalWrite(relay_3, HIGH);
switch_3_ON = 0;
}
}
//**************************************
//Switch 4 configuration
//**************************************
if (digitalRead(switch_4) == HIGH)
{
if (switch_4_ON == 0 )
{
digitalWrite(relay_4, LOW);
switch_4_ON = 1;
}
}

if (digitalRead(switch_4) == LOW )
{
if (switch_4_ON == 1)
{
digitalWrite(relay_4, HIGH);
switch_4_ON = 0;
}
}
}

void Blynk_status() // called every 3 seconds by SimpleTimer
{
bool isconnected = Blynk.connected();
if (isconnected == false)
{
MODE = 1;
digitalWrite(LED1, LOW);
}
if (isconnected == true)
{
MODE = 0;
digitalWrite(LED1, HIGH);
Blynk.syncAll();
}
}

void setup()
{
Serial.begin(115200);
Serial.println("n Starting");
pinMode(button, INPUT);
pinMode(switch_1, INPUT);
pinMode(relay_1, OUTPUT);

pinMode(switch_2, INPUT);
pinMode(relay_2, OUTPUT);
pinMode(switch_3, INPUT);
pinMode(relay_3, OUTPUT);

pinMode(switch_4, INPUT);
pinMode(relay_4, OUTPUT);

pinMode(LED1, OUTPUT);

//*****************************************

digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
digitalWrite(LED1, HIGH);
delay(200);
digitalWrite(LED1, LOW);
delay(200);
WiFi.begin(ssid, pass);
timer.setInterval(3000L, Blynk_status); // check if connected to Blynk server every 3 seconds
Blynk.config(auth);
}

void loop()
{
if ( digitalRead(button) == LOW ) {
WiFiManager wifiManager;
if (!wifiManager.startConfigPortal("Home Automator","1234")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.reset();
delay(3000);
}
Serial.println("connected...:)");
}
if (WiFi.status() == WL_CONNECTED)
{
Blynk.run();
}

timer.run(); // Initiates SimpleTimer
if (MODE == 0)
internet();
else
no_internet();
}

Please help me. I tried a lot to fix it but nothing happens. I checked the Com port in device manager and all the other necessary settings all were right here are the settings in Arduino ide. Please help me Thanks in advance.

what is wired to the pins of the Wemos?

Do you have the serial monitor open while you're trying to upload?

yes I also tried to upload code by closing the serial monitor

no wires are attached to wemos d1 mini

shorts on headers soldering?

no shorts on headers I double-checked all connections with multimeter

You must not have the serial monitor open while uploading. It interferes with the communication and the response from the board goes to the serial monitor not to esptool.py.


text:
Is there a limitation of how many instances of the `String` class?
Platform

Attiny85 with AttinyCores
1306 OLED i2c with Tiny4KDisplay

Goal

using a joystick for menu navigation

up/down choose
left enter (not finished yet)
right back (not finished yet)
inverse display the chosen item.

I come from python word which is why I am using a linked list for menu navigation. I found a weird bug that stops me from displaying some of the long text. I found that if the defined Nodes over a certain amount of number, item text over 5 chars will not display. I don't know why this is related to the number of instances. I managed to narrow down the range of the bug. In the code. if those 3 lines are commented, all the items are displayed correct, if not, only up to ccccc but not dddddd.

The flash and RAM consumption of the failure situation is
Sketch uses 5180 bytes (63%) of program storage space. Maximum is 8192 bytes.
Global variables use 280 bytes (54%) of dynamic memory, leaving 232 bytes for local variables. Maximum is 512 bytes.

My code is as below. I broke it into parts to highlighted the problem. But it is a continuous file actually.
Thank you for any insight.
PS: I know there are methods that avoid oop, but I think this weird bug is so close to being fixed, (or proved to be an actual bug in the package/compiler). So I would like to pursue an answer to this question.
Update:
I tried to use another method that uses a List of Strings instead of a class to achieve the same function. The Bug is still there. I guess it is because there are too many instances of String. The question is not changed: "Is there a limitation of how many instances of the String class?".

#include <Tiny4kOLED.h>

// input setup
int x = 512;
int y = 512;
int lastx = 512;
int lasty = 512;

bool left = false;
bool right = false;
bool up = false;
bool down = false;

char input() {
  x = analogRead(A2);
  y = analogRead(A3);
  if( (lastx > 256) & (x <= 256) ){
    left = true;
  }
  if( (lastx < 768) & (x >= 768) ){
    right = true;
  }
  if( (lasty > 256) & (y <= 256) ){
    down = true;
  }
  if( (lasty < 768) & (y >= 768) ){
    up = true;
  }
  lastx = x;
  lasty = y;
}

// item data
class Node
{
  public:
    String text;
    uint8_t id;
    Node * next;
    Node * previous;
    Node * parent;
    Node * child;
    Node(String s, int n){
      text = s;
      id = n;
      next = NULL;
      previous = NULL;
      parent = NULL;
      child = NULL;
    }
    void append_next(Node * other){
      this->next = other;
      other->previous = this;
      other->parent = this->parent;
    }
    void append_child(Node * other){
      this->child = other;
      other->parent = this;
    }
};

Node main_0("aaa", 1);
Node main_1("bbbb", 2);
Node main_2("ccccc", 3);
Node main_3("dddddd", 4);
Node main_4("eeeeeee", 5);
Node main_5("ffffffff", 6);

This is how the error can be repeated.
/* Uncomment The following 3 lines will cause the problem*/
//Node item_0_0("aaa", 7);
//Node item_0_1("bbb", 8);
//Node item_0_2("ccc", 9);

Node * current_sel = (&main_0);
Node * screen_top = (&main_0);

void setup() {
  // oled setup
  oled.begin(0,0);
  oled.enableChargePump();
  oled.setRotation(1);
  // oled.setInternalIref(true);
  oled.enableZoomIn();
  oled.setFont(FONT6X8);
  oled.clear();
  oled.switchRenderFrame();
  oled.clear();
  oled.switchFrame();
  oled.on();
  // oled setup end

  // input setup
  pinMode(A2, INPUT); // X
  pinMode(A3, INPUT); // Y
  // input setup end

  // data
  main_0.append_next(&main_1);
  main_1.append_next(&main_2);
  main_2.append_next(&main_3);
  main_3.append_next(&main_4);
  main_4.append_next(&main_5);
}

void loop() {
  // input read
  input();

  // move current;
  if(up){
    up = false;
    if(current_sel->previous != NULL){
      if(screen_top == current_sel){
        screen_top = screen_top->previous;
      }
      current_sel = current_sel->previous;
    }
  }

  if(down){
    down = false;
    if(current_sel->next != NULL){
      if(screen_top->next->next->next == current_sel){
        screen_top = screen_top->next;
      }
      current_sel = current_sel->next;
    }
  }

  // oled update
  oled.clear();

  oled.setCursor(64, 0);
  oled.print(current_sel->text);

  Node * current_draw = screen_top;
  int i = 0;
  while(true){

    oled.setCursor(0,i);
    if(current_draw == current_sel){
      oled.invertOutput(true);
    }
    oled.print(current_draw->text);
    oled.invertOutput(false);

    if(current_draw->next == NULL){
      break;
    }

    current_draw = current_draw->next;
    i++;
    if(i >= 4){
      break;
    }
  }

  oled.switchFrame();
  delay(50);
}

what is the memory consumption reported be Arduino IDE at the end of the compilation?

@Juraj Thanks for your comment. The report of the failed one is "Sketch uses 5180 bytes (63%) of program storage space. Maximum is 8192 bytes.
Global variables use 280 bytes (54%) of dynamic memory, leaving 232 bytes for local variables. Maximum is 512 bytes.
"

Each instance of your class uses RAM to store its data. There is always a limit to the number of instances; not a fixed number, but a limit imposed by the quantity of RAM available. What Majenko wrote about Strings applies equally to class instances, if instances are constructed and destroyed during the run.
A fixed number of global instances, as you have used, is more efficient but there is still only room for so many. Complicating this is the fact that RAM is a shared resource. Static variables like globals, including global class-instances, are assigned from the bottom of RAM, upward, after all of the compilations are done and before uploading to the chip. The program's run-time stack, which includes each function's automatic local data, builds from the top of RAM, downward, during the run. Stack memory is assigned and released as each function is entered and exited. But when a function calls a function which calls a function, which calls ..., the stack has to keep growing until the final call returns and the previous calls may then return.
If you attempted to define a large number of instances with a small amount of RAM available, the IDE (actually the linker, which puts together all of your code and the libraries you use) would catch the problem before your program gets uploaded.
But in the case where there all of the RAM didn't get assigned at compile- or link-time, then at run time, your stack could still possibly grow downward until it collides with the global- and fixed-data at the bottom of RAM, with (unfortunately) unpredictable results, but definitely unexpected and improper operation.
Update:
I did gloss over some details, as two commenters were kind enough to point out. Yes, the heap - memory allocated dynamically at run-time - occupies the space just above the globals and other static memory allocations. Heap space can grow, the more it is used to allocate and de-allocate memory, and being low in memory, would have to grow upward, toward the stack. It is the heap where String data is allocated and re-allocated and is one of the reason's behind Majenko's warning against using the String type - especially if the strings will be edited at run time, which results in re-allocation that may not be obvious.
It is also worth noting that any class uses memory, whether Strings or user defined classes such as the OP's nodes. They are both classes and their instances will be handled similarly.
Also in OP's case, note that the class instances are allocated 'statically' - all instances are known and allocated during the run setup and not altered during the run. In 'quotes', because the allocation actually does happen during run-time, but at the very start of the run, and prior to the user sketch receiving control.

Great answer. It should probably also mention heap fragmentation though. (It sounds like the OP uses a fixed number of statically allocated objects, so it might no be relevant here, but if you're gonna give a nice complete answer...)

The stack will collide with the heap before reaching .bss or .data.

Do not use String. Ever. Especially not on a chip with such a tiny amount of RAM.
String uses dynamic allocation to store the string data in RAM. This is very inefficient, especially when you are working with string literals.
Those literals must be stored in flash, not RAM, so you need to be working with const char * and PROGMEM, along with the F() macro.
When using a chip with only a few hundred bytes of RAM you need to be as efficient as you possibly can. You need to account for each and every byte you use - and you just can't do that with String.

As an example, let's look at what this does:
Node main_5("ffffffff", 6);

You have a string of 8 characters plus a NULL terminating character. That's 9 bytes.  Those 9 bytes are copied into RAM at boot time. Current total 9 bytes. You then convert that to a String and copy the character data into that temporary object - that's now 18 bytes plus the size of the String object. Then:
text = s;

You allocate 9 bytes inside the text String object and copy the data in.  You're now at 27 bytes plus two String objects (one of which you created earlier in your class).  A little over 5% of your entire memory just to move text around the place.  A third of that you claw back from your heap as the objects leave scope, but then you have a hole in your heap. And this is the last set of operations after you've already made a complete mess of your heap with the earlier ones.
Whereas
const char main_5[] PROGMEM = "ffffffff";

uses just 2 bytes of RAM to store the pointer and nothing else.

Thank you so much for your answer. I accepted the other one because it shows more insight into why that bug is happening. But your answer actually led me in the right direction. I end up writing a python code dealing with the linked list stuff and generates related C code that defines data in the Flash memory.


text:
RCSwitch for Alarm System
Folks,
I use the RCSwitch sketch to notify my WiFi alarm controller when a motion is detected.
Using the Receiver Code, I have got the following information related to the motion detection signal from the PIR (detector):
Decimal: 8876073 (24Bit)
Binary: 100001110111000000101001
Tri-State: not applicable
PulseLength: 311 microseconds
Protocol: 1
Raw data: 9700,1096,264,400,952,420,964,380,968,372,1012,1040,316,1028,324,1016,380,332,1008,1012,340,1040,344,1000,348,356,1024,324,1016,332,1012,372,1016,336,1012,372,1008,1016,336,328,1016,1008,380,324,1016,368,1012,1008,344,

My Transmitter Sketch is as follows:
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
void setup() {
 Serial.begin(9600);
 // Transmitter is connected to Arduino Pin #10
 mySwitch.enableTransmit(10);
 // Optional set pulse length.
 mySwitch.setPulseLength(312);
 // set protocol (default is 1, will work for most outlets)
 // mySwitch.setProtocol(2);
 // Optional set number of transmission repetitions.
 mySwitch.setRepeatTransmit(5);
 pinMode(13,OUTPUT);
}
void loop() {
 mySwitch.send("100001110111000000101001");//Detection Signal
 //mySwitch.send("100001110111000000101001");//Detection Signal
 //mySwitch.send("101110100000000011000010");//Panic Signal
 //mySwitch.send("101110100000000011000010");//Panic Signal
 Serial.print("Sent 100001110111000000101001 ");
 digitalWrite(13,HIGH);
 delay(500);
 digitalWrite(13,LOW);
 delay(10000);
}

While it appears the message is being sent, unfortunately my Alarm Control doesn't detect it.
Can anyone suggest a fix please?
Ranjith

why do you expect the alarm control to accept communication from the arduino? ... it seems that it would be a security failure if the code was accepted

I need to replace the unreliable wireless alarm system with a new wired system which I have built using good components. However, I also need to use the old wireless security controller to take the advantage of the wireless notification function of it. Given that none of the detectors communicates to the security controller, the security of the system will not be compromised.


text:
How do I make two (or more) pins available on my server url?
I have a webserver configured on my esp8266 with is set to fire off electrical relay0 on my 8 port relay board.
The device initializes relay0 perfectly and without errors.
But when I configure the second relay1, i get no response from my second url.
//note, when you write to low, you turn the switchport on. It's backwards for some reason
#include <ESP8266WiFi.h>
#define statusLed 2   // built-in led for the ESP8266-12

const char* ssid = "myssid";
const char* password = "mypass";

int switchPin0 = 16;
int switchPin1 = 5;
int switch0;
int switch1;

WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);

  pinMode(statusLed, OUTPUT);
  pinMode(switchPin0, OUTPUT);
  digitalWrite(switchPin0, HIGH);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  digitalWrite(statusLed, HIGH);
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);

  client.flush();

  // Match the request

  int value = HIGH;
  if (request.indexOf("/SWITCH=0") != -1){
    digitalWrite(switchPin0, LOW);
    digitalWrite(statusLed, LOW);   // blink led
    delay(1);
    digitalWrite(statusLed, HIGH);
    //set water pump time here
    delay(8000);
    digitalWrite(switchPin0, HIGH);
    value = HIGH;
    ++switch0;
  } else if (request.indexOf("/SWITCH=1") != -1){
    digitalWrite(switchPin1, LOW);
    digitalWrite(statusLed, LOW);   // blink led
    delay(1);
    digitalWrite(statusLed, HIGH);
    //set water pump time here
    delay(8000);
    digitalWrite(switchPin1, HIGH);
    value = HIGH;
    ++switch1;
  } else {

    }

  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("");

  client.print("Switch pin is now: ");

  if(value == HIGH) {
    client.print("Off");
  } else {
    client.print("On");
  }
  client.println("

");
  client.println("Switch 0");
  client.println("Click here  to send a measured amount
");
  client.println("Number of times plant 0 has been fed is ");
  client.println(switch0);
  client.println("

");
  client.println("Switch 1");
  client.println("Click here  to send a measured amount
");
  client.println("Number of times plant 1 has been fed is ");
  client.println(switch1);
  client.println("");

  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
  digitalWrite(statusLed, LOW);   // blink led
  delay(1);
  digitalWrite(statusLed, HIGH);

}

my counter will update, but the relay pin never fires for relay1. relay0 works fine. I can swap the ports and then the second relay will work and not the first. I just can't manage both.
How do I get a second (or more) relay ports to initialize via webpage?

It looks like you forgot to initialize switchPin1 to be an output.
Add the following to your setup() (for example, right after the corresponding initialization commands for switchPin0):
void setup() {
    ....
    pinMode(switchPin1, OUTPUT);
    digitalWrite(switchPin1, HIGH);
    ....
}

wow, what a horrible oversight on my behalf. Thank you. You nailed it.


text:
Using a Encoder Feedback to control a 360 degree servo
I pieced together a sketch to control a servo that turns an encoder. Eventually I plan to build this up to a DMX input, so I have the input range from 0 - 255.
Basically, it's supposed to ask you to input range from 0 to 255 and then it changes that value to 0 -180 for servo control. Then it's supposed to compare that to the encoder and rotate the correct direction until the encoder value and requested values match. I'm just learning arduino so I'm sure I've made some mistake. Here is the code:
// Rotary Encoder Inputs
#define inputCLK 22
#define inputDT 24

#include <Servo.h>

Servo myservo;
int pos = 90;
int counter = 90;
int currentStateCLK;
// Setup Serial Monitor

// Read the initial state of inputCLK
// Assign to previousStateCLK variable
int previousStateCLK;

String encdir ="";

void setup() {
  Serial.begin (9600);
  previousStateCLK = digitalRead(inputCLK);
  // Set encoder pins as inputs
  pinMode (inputCLK,INPUT);
  pinMode (inputDT,INPUT);
  myservo.attach(9);

void loop() {
  Serial.println("Enter a number from 0 to 255");
  while (Serial.available() == 0); {}
  int val = Serial.parseInt(); // read int or parseFloat for ..float...
  long Pos = val;
  Pos = Pos * 180 / 255;
  Serial.println(val);
  Serial.println(Pos);
  if (Pos > Counter) {
    myservo.write 0;
  }
  if (Pos < Counter) {
    myservo.write 180;
  }
  if (Pos = Counter) {
    myservo.write 90;
  }

  // Read the current state of inputCLK
  currentStateCLK = digitalRead(inputCLK);

  // If the previous and the current state of the inputCLK are different then a pulse has occured
  if (currentStateCLK != previousStateCLK) {
    // If the inputDT state is different than the inputCLK state then
    // the encoder is rotating counterclockwise
    if (digitalRead(inputDT) != currentStateCLK) {
      counter --;
      encdir ="CCW";
    } else {
      // Encoder is rotating clockwise
      counter ++;
      encdir ="CW";
    }
    Serial.print("Direction: ");
    Serial.print(encdir);
    Serial.print(" -- Value: ");
    Serial.println(counter);
  }
  // Update previousStateCLK with the current state
  previousStateCLK = currentStateCLK;
}

So when I run the program, I'm not getting any movement on the servo.
Thanks.

reduce your code to only turn the servo in one direction ... nothing more ... it is pointless to even look at your code until you verify that the servo actually works

Your initial problem is here:
  if (Pos = Counter) {

If the result (fall through) of assigning Counter to Pos is non-zero then stop.
That's not right.  You're assigning, not comparing. In C == is comparison and = is assignment.  Instead it should read:
  if (Pos == Counter) {

However there is another, more sneaky, problem with your code - the usage of Serial.parseInt().
If you send the string 56\r\n as you typically would (with the CR+LF line ending typical of serial communication) then parseInt will read the first portion of the string up to and including the first non-digit character and parse it as a number. That is, the 56\r and return the value 56.  Then on the next pass it will see there is still data in the serial buffer and parse it, up to and including the first non-digit character - which is just \n. So it will return 0.
That means the first pass through loop() you get 56, and then immediately after in the next pass through loop() you get 0.
And then, looking at your code a third time, there is another bigger problem: you block waiting for serial input, and your Pos variable is local and will be lost each iteration. I think you meant to use pos, which is a global variable, and not create a new long Pos variable each iteration. And where is Counter defined? That surely should be the global counter variable?
If you're blocking waiting for serial input then how can you be controlling the servo to get it to the desired location?
So, in short, there are so many errors and problems with your code that you need to go back to basics and re-think / re-write many portions of it.


text:
How to make motors start when pressing a button, and then go through a cycle with a specific motor order?
I'm very new to arduino and have to work on a project for school. We have connected 3 motors (Servo, Stepper (180 degrees) and a DC motor) to an Arduino Uno, Adafruit motorshield and a pcb. With the pcb we were able to record values of the motors individually and use these values to create a playback motion. The code which we got for the playback motion is below (I've already filled in my values for the 3 motors).
This is what I want to do with the motors:
When I press a button I want to 'start' the cycle of motor motions

first the dc motor starts doing the motion based on the chosen values
When this stops after 5 seconds I want the servo motor to do it's motion
When the servo motor is done, I want the stepper motor to start doing the motion based on the chosen values for 5 seconds and then stop.

We were told not to use a delay and someone suggested to use millis() instead of delay() but since I am a beginner I have no idea where to start.
This is the code:
// With this code it is possible to play back recorded motion paths for for motors connected to the Adafruit motorshield

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <Servo.h> // this is a library that allows you to drive servo's.

// variables
int modeChoice = 0;

int buttons = A2;  // the three buttons share an analog pin, resitors provide different levels that point to which button is pressed
int slide = A1;    // the slide is read through one analog pin, resitors provide different levels that point to which slide position is current
int rotation = A0; // the pin for the potentiometer

int buttonPressed = 0; // a variable to remember which button is pressed, it is used to control leds and motion memory position management

int buttonValRaw = 0; // a variable to store the raw analog reading of the buttons pin
int slideValRaw = 0;  // a variable to sore the raw analog reading of the slide pin
int valButton = 0;    // a variable to store the interpreted value, the exact pointer to a button
int valSlide = 0;     // a variable to store the interpreted value, the exact pointer to a slide position
int idleState = 0;    // a variable to toggle the servo idle behavior
int resetMotion = 0;  // a variable to return the arrayPosition to 0 if a button is pushed so that the behaviour starts at the beginning
int motionVar1;       // a variable to hold a motion position
int motionVar2;       // another variable to hold a motion position

int mySensorArray[20];  // an array with 20 slots to store raw potentiometer readings (for filtering)
int sensorArrayPos = 0; // the array position of interest.

//////////////////////////////////////

int servoMotionArray_B1[50] = {95, 95, 95, 95, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // paste your 50 values in between the brackets

int DCMotionArray_B1[50] = {-85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85, -85};

//recorded motions for position implementation
int StepperMotionArray_B1[50] = {-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200,-200};

//////////////////////////////////////

int arrayPosition = 0;

unsigned long mainTimer = 0; // a variable to time recording and playback
int timeBetweenSamples = 100; // the time between samples.

unsigned long debounceTimer = 0; // a variable to control a timer interval for debouncing of the buttons
int lastValButton = 0; // a variable to help debouncing of the buttons
int debounceFlag = 0; // another variabel to help debouncing of the buttons

// Setup motors
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Connect a stepper motor with 16 steps per revolution (2048 positions) to motor port #1 (M1 and M2) -- you need to change this if your stepper is on port #2
Adafruit_StepperMotor *myStepper = AFMS.getStepper(16, 1);
// And connect a DC motor to port M3 -- you need to change this if your DC is on a different port
Adafruit_DCMotor *myMotor = AFMS.getMotor(3);

Servo myservo1;   // servo object (employs the servo library that was included above)

// these are dedicated functions to make the steppermotor move
void forwardstep1() {
  myStepper->onestep(FORWARD, SINGLE);
}
void backwardstep1() {
  myStepper->onestep(BACKWARD, SINGLE);
}

//create aStepper object
AccelStepper aStepper(forwardstep1, backwardstep1); // use functions to step

// setup
void setup() {
  Serial.begin(9600); // start serial communication with 9600 baud rate

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

  myservo1.attach(9); // attach servo object to pin 9

  // turn on motor M3
  myMotor->setSpeed(0);
  myMotor->run(RELEASE);

  // setup the stepper
  aStepper.setSpeed(0); // this is used in the 'speed' implementation

  aStepper.setMaxSpeed(200.0); // these are used in the 'position' implementation
  aStepper.setAcceleration(100.0);
  aStepper.moveTo(0);

  // synchronize the first timer cycle -- because the timer is starting at zero it generates negative values in the first 100 miliseconds after starting up when going through the timer cycle, creating potential erratic bahaviour-- giving it a delay at the end of the setup loop will eradicate this behaviour
  delay(1000);
}

void doButtons() {
  if (buttonPressed != 0) {
    return;
  }
  else {
    buttonValRaw = analogRead(buttons);
    valButton = map (buttonValRaw, 49, 605, 0, 5);
    int localButtonVal = valButton;

    if (valButton > 7) {
      return;
    }

    if (debounceFlag == 0) {
      debounceTimer = millis();
      debounceFlag = 1;
    }

    if (debounceTimer < millis() - 20) {

      buttonValRaw = analogRead(buttons);
      valButton = map (buttonValRaw, 49, 605, 0, 5);

      if (valButton == localButtonVal) {
        debounceFlag = 0;

        switch (valButton) {
          case 1:
            buttonPressed = 1;
            break;
          case 2:
            buttonPressed = 2;
            break;
          case 3:
            buttonPressed = 3;
            break;
          default:
            buttonPressed = 0;
            break;
        }
      }
    }
  }
}

void loop() {
  doButtons(); // this uses the buttons from the PCB, if you use your own implementation you need to reprogram this function

  if (mainTimer < millis() - timeBetweenSamples) { // sampling only once per interval.
    mainTimer = millis(); // time is rewritten to current millis starting a new interval.

    if (buttonPressed == 0) { //'idle play'
      if (idleState == 0) {
        motionVar1 = servoMotionArray_B1[arrayPosition];
      }
      else if (idleState == 1){
        motionVar1 = servoMotionArray_B1[arrayPosition];
      }
      motionVar2 = DCMotionArray_B1[arrayPosition];
      myservo1.write(motionVar1);
      if (motionVar2 < 0) {
        myMotor->run(BACKWARD);
        myMotor->setSpeed(abs(motionVar2));
      }
      else if (motionVar2 >= 0) {
        myMotor->run(FORWARD);
        myMotor->setSpeed(motionVar2);
      }
      arrayPosition++;
      if (arrayPosition > 49) {
        arrayPosition = 0;
        idleState = !idleState;
      }
    }

    if (buttonPressed == 1) { //2nd behaviour
      if (resetMotion == 0) {
        arrayPosition = 0;
        resetMotion = 1;
        myMotor->run(RELEASE); // release the DC motor, otherwise it will continue spinning at the last known RPM
      }
      motionVar1 = servoMotionArray_B3[arrayPosition];
      motionVar2 = StepperMotionArray_B1[arrayPosition];
      myservo1.write(motionVar1);
      aStepper.moveTo(motionVar2);
      arrayPosition++;
      if (arrayPosition > 49) {
        arrayPosition = 0;
        buttonPressed = 0;
        resetMotion = 0;
      }
    }
  }

  // one of these needs to be called to make the stepper motor work, comment out the one you do not need (position or speed)
  //aStepper.run(); //stepper position implementation
  aStepper.runSpeed(); //stepper speed implementation

}

You're almost correct already:
if (millis() - mainTimer >= timeBetweenSamples) {
  mainTimer = millis();
  // executing only once per interval.

  ... the action for current arrayPosition ...

  arrayPosition++;
  if (arrayPosition > 49) {
     arrayPosition = 0;
     buttonPressed = 0; // Show ends
  }
}


text:
3v3 ESP one way communication with 5 V Arduino?
Perhaps I'm not fully understanding a difference between logic level and the function of the TX and RX pins? I'm just wondering if an ESP can send, one-way, data to an Arduino. (I found that two-way communication would need a logic level converter.)
ESP32 Datasheet

https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#page=42

Arduino datasheets do not appear to specify logic level tolerances. It appears from this Arduino Forum post, it would work.
Is it universally assumed that 3v3 will be in tolerance for logic high?

https://learn.sparkfun.com/tutorials/logic-levels/all

Yes, it will work, but only just. It's borderline.
The ESP32 gives out at most 3.3V as a HIGH signal. The Arduino accepts "above 0.6Vcc" as a HIGH signal. That means that it needs to see a voltage that is at least 60% of the voltage on the Vcc pin (5V pin) of the Arduino.
If the Arduino has exactly 5V then 60% of that is 3V. Since 3.3V is higher than 3V it sees it has a HIGH.
However if the Arduino is being powered by a slightly higher voltage than 5V (some USB ports can give out 5.2V and it's still in spec) and if the ESP32 is being powered slightly below 3.3V, then that 0.3v margin of error gets narrower and narrower. Eventually it disappears and HIGH can no longer be detected.
For example if the Arduino has 5.2V and the ESP32 has 3.1V then the Arduino expects at least 3.12V and the ESP32 gives out no more than 3.1V.
So in  most circumstances it does work, but there are factors that can stop it from working. Those factors can be mitigated by using logic level translation.

The factor 0.6 itself is chosen to be on the safe side, too. Nobody assures that 2.6V is never interpreted as HIGH. Your final statement is very correct, though.

@DataFiddler It's not safe to second-guess the datasheet. The values given are the guaranteed values. Sure, it may be lower, but it's not safe to assume that. Different chips from different batches could be different, but they are all guaranteed to be no more than 0.6Vcc. 90% of the time it's fine though and for Arduino usage fine is usually good enough. Personally I only usually work with 3.3V microcontrollers anyway (who really uses 5V these days?!)

Additionally, partly contradicting my yesterday's opinion, the 0.6 is part of a well defined hysteresis functionality: An input pin is either LOW or HIGH:  It switches LOW->HIGH @0.6 Vcc, and switches back HIGH->LOW @ 0.3 Vcc This is a feature one can rely on as well.


text:
SoftWire Library Programming Questions for I2C with Digital Pins
I am trying to use 3 TOF10120 Laser Sensors with one Arduino that all have the same, fixed I2C Address. I don't believe it is possible to change the I2C address of the TOF10120, but if I am wrong, please let me know (also, I need 3 different addresses). This being said, I am trying to use the SoftWire Library (https://github.com/stevemarple/SoftWire - very interesting library, but not great documentation) to help me to use my three sensors with Digital Pins. Does anyone have any experience with the SoftWire Library and how to get readings from a laser sensor?
I can provide the code I have, but it probably wouldn't be very helpful anyway. I am particularly curious as to how to use the DigitalWrite() and DigitalRead() functions for I2C with SoftWire.
Thanks for all the help in advance!

you are asking questions about a sensor, but you have not provided any documentation for the sensor

The datasheet is in another language - it isn't helpful at all. The default address is 0x52 for I2C. I bought the sensor from here: https://www.amazon.com/Taidacent-100-1800mm-Distance-Infrared-Detector/dp/B07KW1XN5X

foreign language datasheet is more useful than no datasheet

Link to Datasheet PDF in Google Drive: https://drive.google.com/file/d/1KAIB9xDaO4HcIDBsFz9ia2koAKH_af-_/view?usp=sharing

that datasheet has enough english to find what you need ... there appears to be a command to set the I2C ID ... use google translate to confirm

Would you mind telling me on what page and in what location/line on that page that command is? Also, how do you even send the sensor the command?- any resources for doing so would be greatly appreciated.

I found where it is, but am unsure of exactly how to proceed. Is the command s7-xxx#? How would I even send this command to the sensor? I wouldn't think it would be via the Arduino IDE.

connect one sensor to arduino and use a sketch to send the command

You may use the SoftWire library for that. You may share the SCL lines and have one SDA line for every sensor. Look at the "ListDevices" example of the SoftWire library; you will have to create three SoftWire objects with different SDA pins. Alternative, you may use an I²C multiplexer like TCA954x (there are breakout boards available), which is more convenient as you can use the default (hardware) Wire library and save space and cycles.

You can change the tof10120 to any i2c address between 1 and 254. you need to write the serial string 's7-xxx#' where xxx is the decimal address required (in string form). I wrote a simple python program for the raspberry pi to change my sensor addresses via the Rx Tx.

If would be good to add a reference to where that information can be found in official documentation if possible.  From what I gather the change is perminant, or rather non-volatile.  If that's correct, it might be good to say.


text:
EEPROM programmer works with serial monitor but not with pySerial
I'm trying to modify Ben Eater's eeprom programmer to flash a 32K eeprom, since the arduino has 32K of program data total the data wouldn't fit in the program. So I wrote a python program using pySerial to send the data in chunks of 256 bytes over serial. The arduino program works correctly when I manually send the data over the serial monitor, and the python program works correctly when I print the values to a console as a test, but when I actually run the program over serial it seems to only write zeros to the eeprom. Additionally, the Rx led on the arduino seems to be lighting up with the correct data, but like I said only zeros are written.
Here's the relevant arduino code:
void setup() {
  pinMode(SHIFT_DATA, OUTPUT);
  pinMode(SHIFT_CLK, OUTPUT);
  pinMode(SHIFT_LATCH, OUTPUT);
  digitalWrite(WRITE_EN, HIGH);
  pinMode(WRITE_EN, OUTPUT);

  Serial.begin(57600);
  dataArrPage = 0;

  //delay(1000);
  //Serial.println("Reading EEPROM");
  //printContents();

}

void loop() {
  if (Serial.available() > 0) {
    int len = Serial.readBytes(dataArr, 256);

    for (int i = 0; i < 256; i++) {
      writeEEPROM(dataArrPage + i, dataArr[i]); // writeEEPROM(address, data)
    }
    dataArrPage += 0x100;

    Serial.write('s'); //success, writing is done
  }
}

And the relevant python code:
import time
import serial
ser = serial.Serial('/dev/ttyUSB0', 57600)
time.sleep(4) # wait for arduino to initialize

filename = input("Enter file name: ")
f = open(filename, "rb")
data = f.read()

page = 0
for x in range(128): # 128 pages in 32K eeprom
    for i in range(256):
        #print(hex(data[(page * 256) + i])) # printing prints the correct values
        ser.write(data[(page * 256) + i])
    page += 1

    #wait until receive 's' from arduino
    while True:
        if ser.in_waiting > 0:
            suc = ser.read(size=1)
            if suc == b's':
                print("Success")
                break

print("Writing done")
f.close()
ser.close()

I'm a beginner so sorry if it's something obvious.

And if you wait for the Arduino to reboot and pass the bootloader after you open the serial port?

I had a delay after opening the serial port in the python code but it didn't make a difference, entering the file name takes a bit anyways. I should probably add it back in.

You should consider a two-way protocol, so Python sends something then the Arduino responds once that operation is done with a status. That way you know what is happening from both ends.

Okay, I'll try that.

I edited the code to print "Success" when the arduino is done writing the 256 bytes, however it only prints success 3 times then freezes. Would the contents of the file matter at all? It's a 32K file that's mostly zeros after some text at the beginning.

This is probably the sort of thing that would be better to work out on a chat network.  If you're going through it bit by bit there's not going to be a clear question with a clear answer.

I figured out the problem. The for loop was writing one byte at a time, which probably wasn't fast enough and caused a timeout in the arudino. The code is now:
page = 0
for x in range(128): # 128 pages in 32K eeprom
    datalst = []
    for i in range(256):
        datalst.append(data[(page * 256) + i])

    ser.write(datalst)

    #wait until receive 's' from arduino
    while True:
        if ser.in_waiting > 0:
            suc = ser.read(size=1)
            if suc == b's':
                print("Success")
                break

    page += 1

I also changed the data types in the arduino sketch to use the ones in stdint.h which solved an unrelated bug. Let me know if I should post the full code for both.

Hm, strange. Since your line runs with 57600 baud, it transfers just some 6000 bytes per second. I would think that the Python loop runs faster. -- However, if the USB-based serial interface connects directly to a USB module inside the AVR, the baudrate is not maintained.


text:
How to connect an lcd i2c using only pins A0 and A1 (SDA, SCL, GND, and VCC are given)
I want to know how to connect an lcd i2c, with an led 8x8 matrix at the same time. The problem is, all the analog in pins are used, except A0 and A1. Using this tutorial:
https://www.makerguides.com/character-i2c-lcd-arduino-tutorial/
It says I must have analog pins A0-A2 with nothing connecting, except I have A2 connected, which is why both screens don't work right. So how can I use only pins A0-A1 with an lcd i2c? Thanks.

You may be finding Connect to LCD via I2C, default address 0x27 (A0-A2 not jumpered) confusing.  These refer to the I2C address selection lines of the IO expander (the PCF8574T) used on the I2C LCD display and not to the A0-A2 analog pins of the Arduino itself.

The note // Wiring: SDA pin is connected to A4 and SCL pin to A5. is referring to the analog pins of an UNO (or Nano) because these pins also happen to carry the ATMega328P's I2C ("Wire") signals.
So there's nothing about using the I2C display that prevents you from using the Analog A0-A2 pins of the Arduino for other purposes.  Only the  Arduino's A4 and A5 pins are used to carry I2C/Wire.


text:
Testing 433MHz Transmitter
Folks,
There is a document named "Complete Guide for RF 433MHz Transmitter.pdf" available in the GitHub.
There is a a connection diagram showing the Data pin of the Transmitter connected to the pin 12 of the Arduino Uno.
The Transmitter sketch given in it is as follows:
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;

void setup()
{
 Serial.begin(9600); // Debugging only
 if (!driver.init())
 Serial.println("init failed");
}

void loop()
{
 const char *msg = "Hello World!";
 driver.send((uint8_t *)msg, strlen(msg));
 driver.waitPacketSent();
 delay(1000);
}

There is no mention of Pin 12 as part of the sketch. I am not sure how the Arduino knows the Transmitter Data input is connected to the Pin 12? Can someone please help?
Ranjith

In RH_ASK.h is:
RH_ASK(uint16_t speed = 2000, uint8_t rxPin = 11, uint8_t txPin = 12, uint8_t pttPin = 10, bool pttInverted = false);

So the argument has a default value specified here.  If you don't specify it, it assumes that default.

Thanks a lot. Much appreciated.


text:
Use a simple LED with no digital pins to spare
Problem: I've made a circuit consisting of an 8x8 led matrix, which uses all of the digital pins on the Arduino UNO board, and I want to add an LED too it.
I tried looking around the internet but so far, I have not seen any solution on how to use a simple LED with no digital pins to spare.
So I ask, is it possible to connect an LED with no leftover digital pins? I just want to be able to turn the LED on and off.
Thanks.

Just found this:
https://forum.arduino.cc/index.php?topic=311099.0
Turns out you can use the analog pins of an Arduino UNO using this:
pinMode(A1,OUTPUT);
digitalWrite(A1,HIGH);

You just have to list it as an analog pin. Seems to be working, don't think there are any downsides, as far as I see.

Yup.  Though make sure you see the note there by CrossRoads regarding A6 and A7 on SMT based UNO (and other SMT 328P Arduino).

In a couple days time you'll be able to accept your own answer, and probably should assuming someone else doesn't provide another you like better.

Ok, yeah I'll do that later, unless I get a better answer as you said.


text:
Arduino Project - Social distance detector
I am trying to make a social distance detector for a project of mine. There are many projects online about this, but none of them are the right ones. I'm trying to make a thing that attaches to a lanyard. My original plan was when a PIR sensor detected a human, it would trigger the ultrasonic sensor into measuring the distance between the lanyard and the human. The problem is, the PIR sensor was always displaying "high", and after doing some research, a PIR sensor can be only stationary. I am wondering if there are other easy and cheap options other than PIR sensors that can detect humans accurately? Thanks!

how does attaches to a lanyard make it different from the other projects on the web? ... right now it reads like I'm buiding a race car, but mine will be green

Sorry for not clarifying. The lanyard will be hung around a neck, which is not the same as being a "stationary" human detector that will be attached to a wall.

A normal PIR sensor reacts to movement. It does nit measure distance. Thus it is not interessting for your project. There are other real IR distance sensors. Sensors don't have to be stationary. They will work as long as the involved speed is significantly slower than the sensor. That should be true for IR and ultrasonic sensors for mounting on a human. More important is the direction. When carried around the neck, you need to keep your sensor front facing.

If a PIR sensor doesn't work, what other options I can do to distinguish between humans and objects?


text:
4004 (NOT_FOUND) ON MQTT
I tried to send random data to MQTT but it's not working and I get:

{
   "m2m:rsp" : {
      "rsc" : 4004,
      "rqi" : "123456",
      "pc" : "Resource not found",
      "to" : "5a185cedc6ad749b:edb0b82be780ba6d",
      "fr" : "/antares-cse"
   }
}

This is from mqtt.fx
This is my payload what should I do
    #include <SoftwareSerial.h> //koneksi ke modem

    #define TINY_GSM_MODEM_SIM7000
    #define TINY_GSM_DEBUG SerialMon
    #define BAUD 9600
    #define SerialMon Serial

    SoftwareSerial SerialAT(10, 8); // RX, TX ke modem

    const char apn[]  = "nb1internet"; //untuk gprs gunakan "internet"
    const char user[] = "";
    const char pass[] = "";
    byte randomValue = random(0, 37);
    const char *mqtt_server = "mqtt.antares.id"; //server antares
    const char *mqtt_user = "";
    const char *mqtt_pass = "";
    const int mqtt_port = 1883;
    const char *mqtt_client_name = "KEKW" + randomValue; // random

    //dibawah ini sesuaikan dengan akun atares kamu
    #define TOPIKPUB "/oneM2M/req/5a185cedc6ad749b:edb0b82be780ba6d/antares-cse/json"
    #define accessKey "5a185cedc6ad749b:edb0b82be780ba6d"
    #define projDev "ECSENSOR/pHnEC"

    // library modem dan mqtt
    #include <TinyGsmClient.h>
    #include <PubSubClient.h>

    #ifdef DUMP_AT_COMMANDS
      #include <StreamDebugger.h>
      StreamDebugger debugger(SerialAT, SerialMon);
      TinyGsm modem(debugger);
    #else

    TinyGsm modem(SerialAT);
    #endif
    TinyGsmClient client(modem);
    PubSubClient mqtt(client);

    long lastReconnectAttempt = 0;
    int val;

    void setup()
    {
      // Set debug console dan modem
      SerialMon.begin(9600);
      delay(10);
      SerialAT.begin(9600);
      delay(3000);

      String modemInfo = modem.getModemInfo();
      SerialMon.print("Modem: ");
      SerialMon.println(modemInfo);

      SerialMon.print("Waiting for network...");
      if (!modem.waitForNetwork(240000L)) {
        SerialMon.println(" fail");
        delay(10000);
        return;
      }
      SerialMon.println(" OK");

      if (modem.isNetworkConnected()) {
        SerialMon.println("Network connected");
      }

      SerialMon.print(F("Connecting to "));
      SerialMon.print(apn);
        if (!modem.gprsConnect(apn, user, pass)) {
        SerialMon.println(" fail");
          delay(10000);
          return;
      }

        SerialMon.println(" OK");

       // MQTT Broker setup
      mqtt.setBufferSize(512);
      mqtt.setServer(mqtt_server, mqtt_port);
    }

    boolean mqttConnect() {
      SerialMon.print("Connecting to ");
      SerialMon.print(mqtt_server);

      // koneksi ke MQTT Broker
      boolean status = mqtt.connect(mqtt_client_name,mqtt_user, mqtt_pass);

      if (status == false) {
        SerialMon.println(" fail");
        return false;
      }
      SerialMon.println(" OK");

      return mqtt.connected();
    }

    void loop()
    {

      //cek jika koneksi mqtt gagal maka ulang lagi
       if (!mqtt.connected()) {
        SerialMon.println("=== MQTT NOT CONNECTED ===");
        // Reconnect every 10 seconds
        unsigned long t = millis();
        if (t - lastReconnectAttempt > 10000L) {
          lastReconnectAttempt = t;
          if (mqttConnect()) {
            lastReconnectAttempt = 0;
          }
        }
        delay(100);
        return;
      }

      int val = random(0-450);  //TEST RANDOM DATA

      String pubString ;
     //JSON yang panjang untuk kirim data ADC ke antares
        pubString +=  F("{");
        pubString += F("\"m2m:rqp\": {");
        pubString += F("\"fr\": \"");
        pubString += String(accessKey) ;
        pubString += F("\",");
        pubString += F("\"to\": \"/antares-cse/antares-id/");
        pubString += String(projDev);
        pubString += F("\",");
        pubString += F("\"op\": 1,");
        pubString += F("\"rqi\": 123456,");
        pubString += F("\"pc\": {");
        pubString += F("\"m2m:cin\": {");
        pubString += F("\"cnf\": \"message\",");
        pubString += F("\"con\": \"{\\\"level\\\":");
        pubString += String(val);
        pubString += F("}\"");
        pubString += F("}");
        pubString += F("},");
        pubString += F("\"ty\": 4");
        pubString += F("}");
        pubString += F("}");

      // kirim atau publish ke antares
      SerialMon.println(pubString);
      char message_buff[pubString.length() + 1];
      pubString.toCharArray(message_buff, pubString.length() + 1);
      mqtt.publish(TOPIKPUB, message_buff);

    delay(5000);
    }

what you should do is to include the whole sketch


text:
snprintf doesn't display float values
I don't understand why the formatted string is displaying ?? instead of float values.
My code:
#include <Arduino.h>
#include <Wire.h>
#include "SparkFunCCS811.h"
#include <DFRobot_SHT3x.h>

DFRobot_SHT3x sht3x(&Wire, /*address=*/0x44, /*RST=*/4);

//* Get SHT31 readings

void readSHT(float &temp, float &humid)
{

    DFRobot_SHT3x::sRHAndTemp_t data = sht3x.readTemperatureAndHumidity(sht3x.eRepeatability_High);

    char shtVal[50];

    if (data.ERR == 0)
    {
        temp = data.TemperatureC;
        humid = data.Humidity;

        Serial.println(data.TemperatureC);
        Serial.println(data.Humidity);
    }

    snprintf(shtVal, 50, "Temp = %f  Humidity = %f", temp, humid);
    Serial.println(shtVal);
}

void setup()
{

    Serial.begin(115200);

    //*Initialize the chip
    while (sht3x.begin() != 0)
    {
        Serial.println("SHT31 Initialization Failed");
        delay(1000);

        Serial.print("Chip serial number");
        Serial.println(sht3x.readSerialNumber());

        if (!sht3x.softReset())
        {

            Serial.println("Failed to Initialize the chip....");
        }
    }
}

void loop()
{

    unsigned long newTime = millis();
    static unsigned long oldTime = 0;

    if (newTime - oldTime >= 5000)
    {

        float temp = 0.0;
        float humid = 0.0;

        oldTime = newTime;

        readSHT(temp, humid);
    }
}

& here is the output:
Here is what I get as output:
21.23
41.06
Temp = ?  Humidity = ?

The function readSHT()has no problem displaying the actual values but why the formatted string shows ???. Am I doing something wrong?

The standard avr-libc does not have float support enabled in the printf family of functions. This is because float support would bloat your code massively, and most people don't need it.
It is possible to enable it through some black magic (I don't know what, but someone else may), but in general you don't want to since there are better ways.
Typically you would use dtostrf() to format your float into a char array separately. Or if all you are doing is printing to serial then you wouldn't even format it into a string in the first place.
Serial.print(F("Temp = "));
Serial.print(temp);
Serial.print(F("  Humidity = "));
Serial.println(humid);

Ah Ok. I will use dtostrf () as I need to pass these values to another function as well. This way I can store the value with suitable no. of decimal places.


text:
Can RX pin(s) be used as TX instead?

Title question. I do not need any receive communication pins, only transmission.

Actually, I need as many transmission pins as possible on any Arduino besides a Mega2560 (to re/write the EEPROM of slave devices). A Mega2560 has 23 TX/RX pin pairs.
Maybe I'm misunderstanding serial communication. And maybe some sort of multiplexing deal can work like One-Wire temperature sensors...such as softwareSerials[x].write()...

SoftwareSerial serialOne(2, 3); // Software Serial ONE
SoftwareSerial serialTwo(8, 9); // Software Serial TWO
                     // RX, TX

Is there a way to make all the pins using SoftwareSerial TX? Or do half need to be RX?

"Just take a better microcontroller, and that is all." - user1829200

What off-the-shelf microcontroller is geared for serial communication?

what are you trying to build?

@jsotola Two to 20 motor modules controlled by Arduino slave devices (such as Nanos) running simple equations are sent variables from a master device (such as an ESP32).

Are you aware that the Arduino (Uno, Mega2560) do not allow more than one instance of SoftwareSerial? are you sure, because one of the two example sketches uses two SoftwareSerial instances. Only one instance can receive at a time. Maybe that's what you were referring to, but OP only needs TX.

As far as I can see, you can use the same RX pin on all your SoftwareSerial instances. You'd only have to "sacrifice" one pin.

You could also have single serial connecting that's shared with all the Nanos, and add an id to each message. For example, "turn motor 3 on", where only the third Nano would take action on that message.

Ah, yes, thanks Gerben. (The ID approach is what I meant by the One-Wire analogy.)

You might wanna google for a transmit-only software serial library. That will also make the code smaller, as no receive code is included.

One way to communicate Arduino to Arduino device is UART (and Software Serial for additional pins). For the ESP32, it seems this allows 28 TX pins using Majenko's method (in their answer). In other words, slave 28 devices.
After further research, isn't I2C the clear route to go?

With more slave devices the less times per second to talk to them all
The application needs to have all the slave devices execute commands synchronously:

At least, the slave devices need to start functioning at the same time.

How many slave Uno's/Nano's can be connected to an ESP32?

Each device on an i2c network has a 7-bit address, so a single network theoretically supports up to 128 slave devices. In practice though, the limit is much lower. i2c slave chips often support only 8 different bus addresses, no more than 8 of that chip can be attached to the same i2c network.

https://mindbleach.com/words/2012/10/23/i2c-and-device-limits
Unclear answer:

https://forum.arduino.cc/index.php?topic=159860.0
https://forum.arduino.cc/index.php?topic=367961.0

You should be (though I haven't tested it) be able to set the RX pin to an unused pin number, such as 255.  Then the RX pin will do nothing.
#include <SoftwareSerial.h>

SoftwareSerial s0(255, 2);
SoftwareSerial s1(255, 3);
SoftwareSerial s2(255, 4);
SoftwareSerial s3(255, 5);
SoftwareSerial s4(255, 6);
// ... etc ...

The "can't have more than one instance" thing is to do with reception. You can't have more than one SoftwareSerial instance receiving at once - but you don't care about that, since reception is not being used.


text:
Why use \" in arduino code?
While working with JSON parsing I noticed that the char type data string is written like this:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";

Why there are (escapes) " ---" used in the code? Why can't we use the string normally?

Try it without and see what happens ;-)

Why there are (escapes) " ---" used in the code? Why can't we use the string normally?

Because escapes are required.
In C " means 'The start or end of a string', but \" means 'A double-quote character'.
There has to be a way to distinguish a double-quote character from a string delimiter so the compiler knows which is which. Without escapes your string would look like:
char json[] = "{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}";

and the compiler would find the end of the string at the second ", and then a load of junk before it finds the end-of-statement ; character. It can't work out what sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}" is supposed to be, since it isn't in the string, but after it.


text:
Can someone help me figure out why my menu gets stuck?
When I try to run my code so far with the menu and select buttons, it seems that it works, except that the main menu will not move past "Main Garden" to "Currants". There's also a problem with the submenu where after the first watering warning, pressing the select button makes it simply return to the main menu without lighting the LED on the LEDPower pin or running that watering routing for the whole watering interval.
The one guess I still haven't tried is that maybe I should change void MainMenu() to a Switch Case structure instead of If-Else?
.
edit:
.

Problem One (Menu not moving past Main Garden to Currants):
MainOld is used to increment MenuState but MainOld never gets incremented, which means it will never have a value greater than 0. Accordingly MenuState can
never be greater than 0 + 1.
Problem Two (Sub Menu looping back to main):
'Checking' the state of LEDPower like in Water1() is not the best way to accomplish what you want to accomplish. It may work but is not technically correct as LEDPower is a pin state and you never actually read the state.
The other issue in Water1 is that previousWaterMillis doesn't get updated anywhere in your code, which means that anytime Water1 is called more than 10 seconds after boot your solenoid will activate and then immediately deactivate. I would recommend a while loop inside your Water1 function. ex.
void Water1(){
  digitalWrite(Relay1, HIGH);
  unsigned long currentMillis = millis();
  previousWaterMillis = millis();
  int LEDPowerState = digitalRead(LEDPower);

  while(currentMillis - previousWaterMillis <= WateringInterval){
    digitalWrite(LEDPower, HIGH);
    Serial.println("Watering Garden with LED Lit");
    currentMillis = millis();
  }

  digitalWrite(Relay1, LOW);
  digitalWrite(LEDPower, LOW);
  SubMenuState = 0;
  SubMenuOld = 0;
}

^^ This will illuminate your LED and activate the solenoid for the 10 secs you wish to water.

Thank you so much!! I added
 MainOld = MenuState;

to menubuttoncheck() to make MainOld increase with the presses, did void Water1 as you said, and it works!


text:
Arduino modbus program error
I was trying to extract data from a multi-function meter with RS485 connectivity and I am using Arduino as master, Arduino Uno and multi-function meter are connected via MAX485 module.
I have tried some code but it returns an E2 error which means communication error.
Kindly explain me the program and help me to solve it.
#include <ModbusMaster.h>

#define MAX485_DE 3
#define MAX485_RE_NEG 2
ModbusMaster node;

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG,1);
  digitalWrite(MAX485_DE,1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG,0);
  digitalWrite(MAX485_DE,0);
}

void setup()
{
  pinMode(MAX485_RE_NEG,OUTPUT);
  pinMode(MAX485_DE,OUTPUT);
  digitalWrite(MAX485_RE_NEG,0);
  digitalWrite(MAX485_DE,0);

  Serial.begin(9600);

  node.begin(1,Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  uint8_t resultMain;

  resultMain = node.readHoldingRegisters(0x0100,6);
  Serial.print(resultMain,HEX);

  if (resultMain == node.ku8MBSuccess)
  {
    Serial.print(resultMain);
    Serial.print(node.getResponseBuffer(0x32));
  }
  delay(1000);
}

Can you please let us know the energy meter which you are using?

secure ELITE 300

Can you please use software serial for the communication between meter and arduino because your uart can't be shared simultaneously with both the PC and the meter. That could be the reason why it shows you Communication fail error

can you pls send me the example code becaus i have tried that also but ir shing the same error

"means communication error".  More specifically a timeout.

You have node.begin(1,Serial); where 1 appears to be the modbus slave ID.  Is that in fact the ID of your meter?

yes that's the slave id

See whether or not it makes any difference with your A and B signals swapped.

ya i tried that also but same error my register no is 40100 it is an holding register and its length is 32 bit   its hexa value is 0064 i am i making mistake in this anywhere ?

First, use another Serial port for the RS485; if you have an Arduino Mega, you can just use that instead to minimize code changes since it has multiple hardware UARTs. You'll only need to change node.begin(1, Serial) to something like node.begin(1, Serial2). Next, make sure your hardware connections are correct; in addition to the 2 RS485 connections (A and B), there MUST also be a common GND connection between your Arduino and the meter. Verify your connections by using the RS485 connection to send data between 2 Arduinos, without the Modbus layer. Just send strings back and forth.


text:
ESP32 USB HID/MIDI library (not the BLE one)

I couldn't find any library to use an "old" ESP32 (not the new ESP32-S2) as an HID connected physicaly to the Usb port (not over BLE pairing) to send keystrokes to the PC ...
Is there any solution? Any code example, so far?
Thanks in advance!

it is unclear what you are asking ... MIDI is used for musical instruments

Esp32 doesn't have usb.

@jsotola i am trying to send keystrokes to the PC by plugging the (old) ESP32 on to the Usb port

The ESP32 doesn't have USB. You can't do USB communication. All it has is (like the UNO) a USB to UART interface chip. Unlike the UNO this is not programmable (more like a cheap Chinese knock-off UNO clone in that respect).
You would need to couple it with a microcontroller that has USB and program hat to be your USB interface and communicate with it over some other communication medium, such as UART or I2C.


text:
Can i store a SqlLite DB into an (old) ESP32? (not using SD card)
I would like to know if it is possible to store a (little, basic) SqlLite DataBase (or of any other type) into the (old) ESP32.
I don't want to use an SD card for that (for which I already know it is possible).
Thanks in advance for any hint on this

Sure, you can store it. You can store anything you like, size permitting, it's just a file after all. But I assume you actually want to use it from the ESP32 too?

@Majenko sure! ;-) i would load data "once" on programming the ESP32, and then "just" read it to take decissions and drive the program on different settings.

Then a database file is probably overkill. You could just use a simple text file for that.

@Majenko thanks!

I found these two post to be a useful answer to my question:

ESP32: Best way to store data frequently?

Sqlite3 Library for ESP32 Arduino Core

It could be really educating and clarifying if the downvoter would shine to explain why he downvoted... downvoting without an explanation may be considered impolite and unsmart...

Possibly because it mostly consists of links.  You can always add more details on how they helped.  Broadly you can make the answer more useful to future readers.

Yes you can - or you can certainly store it. ESP32 can use its flash as a filesystem (SPIFFS, LittleFS, FAT, etc) so you can store whatever data you like on there.
Whether the SQLite library can work with that file is another matter though, and is something you would have to explore yourself.
However for your use case using a database file is a bit silly. If all you want is some pre-defined runtime settings then all you really need is a simple text file. Maybe something like an INI file (key=value pairs) would be plenty for your needs, and pretty simple to parse without any libraries.


text:
SIM800L module on Arduino nano
I am trying to get Arduino nano and SIM800L module working together. I provided the module with the recommended external voltage of 4.0V (documentation states 3.6V - 4.2V) transformed via LM2596. The original source is 5V 3A.
LED on SIM800L blink once a second as stated in documentation when in an unconnected state.
The schema is the following:
                  Antena
                   \_/
                    |
Arduino    SIM800L  |  External 4.0V
             NET ---/
             VCC ----- +4.0V
D2 --------- RST
D3 --------- RX
D4 --------- TX
             GND ----- GND

I have already tried 3 different libraries for AT communication and also sending raw AT commands using writing to serial manually. I also tried another SIM800L module because I thought the module is faulty.
Here is the dump from serial communication:
[551135] ### TinyGSM Version: 0.10.9
[551139] ### TinyGSM Compiled Module:  TinyGsmClientSIM800
AT
��AT
�AT
H�j���[552012] ### Unhandled: Hj
AT
AT-���[552317] ### Unhandled: AT-
AT
��AT
��AT
�Z5
[553228] ### Unhandled: Z5
AT
␚)O���[553532] ### Unhandled: ␚)O
AT
AT���[553836] ### Unhandled: AT
AT
��AT
��AT
�)OK��[554748] ### Unhandled: )OK
AT
���[555053] ### Unhandled: 5
AT
���AT
��AT
��AT
�j�H�[556266] ### Unhandled: jH
AT
CC����[556570] ### Unhandled: CC
AT
AT���[556875] ### Unhandled: AT
AT
��AT
AT
���[557787] ### Unhandled: T
AT
�H����[558091] ### Unhandled: H
AT
AT���[558395] ### Unhandled: AT
AT
��AT
��AT
AT
jRO���[559610] ### Unhandled: jRO
AT
AT���[559915] ### Unhandled: AT
AT
��AT
��AT
AT
�
OK��[561128] ### Unhandled: OK
Failed to initialize SIM800L

As you can see the module is trying to negotiate the baudrate. By default, I use speed 9600 as stated in the documentation. When I use a different baudrate the module does not respond at all.
It seems the module replies and sometimes even correctly. Response to AT command should be OK.
Do you know how do I successfully negotiate the speed and establish reliable serial communication with the module? Do I miss any electrical components in my circuit like a capacitor or resistor? I tried to use capacitor 35V / 3300µF but without any difference. I think my power source is strong enough.
The source code is the following:
#define PIN_GSM_RST             2
#define PIN_GSM_TX              3
#define PIN_GSM_RX              4
#define GSM_BAUDRATE            9600

#define TINY_GSM_MODEM_SIM800
#define TINY_GSM_DEBUG          Serial
#define TINY_GSM_USE_GPRS       true
#define TINY_GSM_USE_WIFI       false

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <TinyGsmClient.h>
#include <StreamDebugger.h>

SoftwareSerial serial_SIM800L(PIN_GSM_RX, PIN_GSM_TX);
StreamDebugger debugger(serial_SIM800L, Serial);
TinyGsm modem(debugger);
TinyGsmClient client(modem);

void setup() {
    Serial.begin(9600);
    delay(1000);

    Serial.println(F("Serial initialized"));

    serial_SIM800L.begin(GSM_BAUDRATE);
    delay(5000);

    while (!modem.init()) {
        Serial.println("Failed to initialize SIM800L");
    }
}

void loop() {
    //
}

Did you connect the GND of the Arduino with the GND of the SIM800L? I can not see a connection in the schematics.

@PeterPaulKiefer No, I only connected the SIM800L to the ground of the external source. Might that be the problem?

Of cause; All voltages that come from the arduino to the SIM800L must have a reference GND. You need a common potential. If you have none the Arduino is not able to communicate with the module. The GND of all modules and external Powersuplies must be connected. Only if you use a separate circuit, eg. behind a relais, the GND must not be connected.

One additional thing. The Nano is usally  a 5 Volt board. Are you sure the SIM800L pins are 5 Volt tolerant. If you connect GND, they might be faced by 5V. That could kill them, if they are not 5V tolerant.

Max working voltage of SIM800L is 4.2V. If the voltage is higher than 4.4V the module turns off. What schema to use so the module is not exposed to 5V via GND then?

Probably level shifter; or if you have a 3.3 Volt controller (Arduino Due, Micro, 3.3V Nano). As you are not familiar with electronics (I assume), search for arduino projects with SIM800L in the internet. And don't trust all the videos that say it is save to use a SIM 800L with 5V Arduinos. The following might be interesting for you: https://lastminuteengineers.com/sim800l-gsm-module-arduino-tutorial/

I used LM2596 to convert 5V to 4V eventually. I tried resistor level shifter as well before. Many articles I found simply did not use external power but diode voltage drop so board 5V pin could be used and I did not realize that. Your suggestion of connecting GNDs worked. Thank you.

You're welcome. Just to mention it: The Arduino pins that are connected to the SIM Module are 5 Volts. If your Module version has internal protection for these pins, all is fine. But, if the pins are connected without level shifting, the Module might work for a time, but there is a hight possibility that it get's destroyed. Cheers.

Thanks to @PeterPaulKiefer here is the answer.
External power for SIM800L module GND pin needs to be connected to both SIM800L module GND pin and Arduino nano GND pin. (e.g between RST and R2 pin on Arduino nano)
In order for the calling function to work, you also need to use a capacitor on SIM800L VCC and GND pins. I used 35V, 3300µF.
Schema:
                  Antena
                   \_/
                    |
Arduino    SIM800L  |  External 4.0V
             NET ---/
             VCC ----- +4.0V
 D2 --------- RST   |
 D3 ---------  RX  === Capacitor (35V, 3300µF)
 D4 ---------  TX   |
GND --------- GND ----- GND


text:
Non-blocking SoftwareSerial.Write
How to use SoftwareSerial.Write without blocking if buffer is full? Serial.write blocks if the buffer is full. So I need to check Serial.availableforwrite before calling write to prevent blocking. But there is no SoftwareSerial.availableforwrite. How can I use SoftwareSerial.Write without blocking?

AltSoftSerial has availableForWrite()

What's your use case for Software Serial?

In short, you don't.
The SoftwareSerial implementation for AVR doesn't have an outbound buffer at all.
It just turns the interrupts off during each character outbound and it sends them all immediately.
This means a call to SoftwareSerial's write simply will block until all of the data you've tried to send has in fact been sent.  If you can't afford to wait for your data to go out on the TX line now, then it's up to you to send it later when you can afford to wait.
SoftwareSerial has no flow control.  When you write(), the data is sent out on the TX pin regardless of whether anything is present on the other side of the connection.  And when present, the data is still transmitted regardless of whether other side considers itself "ready" to receive.  There's simply no feedback from the receiver to tell the sender to stop.  So SoftwareSerial itself will never block owing to these things.

This means I can call Write whenever I want without a risk of blocking my main program?

I've updated the answer in attempt to address that.

My problem is I can't make sure someone is listening or not. For the program it is not important if someone is listening, but ending in a deadlock is inacceptable.

Updated again in attempt to address that.

Thank you. That helped a lot.

Is the last part (no flowcontrol) identical to the normal Serial.write? So I don't have to check Serial.availableforwrite for Serial.write too?

For Serial (HardwareSerial) on UNO (you have tagged), there's also no flow control between the ATMega328P chip and the serial transceiver (ATMega#U2 or FTDI, CH340, etc).  So it will not block owing to flow control.  You can fill the transmit ring buffer and have to wait for the USART transmit interrupt to drain that ring buffer.  But it will not deadlock.

Thanks again 3moreWords


text:
Where is the positive and negative holes on the arduino mini breadboard?
I have the mini arduino breadboard. The pins go from A to J and 1 to 17. On the larger breadboard, there are symbols + and -. My breadboard doesn't have those two sections to put wires in. Does anyone know what to do?

Does anyone know what to do?

Do whatever you want to do.
There's nothing special about the +/- rails of a breadboard - they're just chunks of metal that go along instead of across, and are longer, with more holes, and someone has helpfully coloured them red/blue and added some symbols.
If you want a common place for + and - then just choose a common place for + and -.


text:
Adafruit_Arcada' does not name a type;
I am trying to program an adafruit pygamer (which says it's compatible with Arduino). I have added the ZIP folder for the library into the library folder om my PC where all of my folders are supposed to be stored, one thing I managed to find out for a start was that the library folder for the library itself that was installed from GitHub contained a dash in the filename so I replaced that for an underscore. The actual error message that seems to come up now is this:
'Adafruit_Arcada' does not name a type; did you mean 'Adafruit_SPITFT'?

This error comes up from when I try to use the:
#include "Adafruit_Arcada.h"

Adafruit_Arcada arcada;

lines
Within the library folder that I want to try and use there are the code examples within the library folder inside the examples sub-folder
I have tried following a step by step guide into one potential way of trying to solve this problem by looking at a tutorial by adafruit on how to step by step install zip folder libraries. Something tells me though that this error that I am getting is to do with one of the .h or .cpp files within the library itself.
The link for the library itself is here: https://github.com/adafruit/Adafruit_Arcada
In addition, when I look in the Adafruit_Arcada.h file I can actually see that there is no Adafruit_Arcada class but there is an Adafruit_SPITFT one. I know this point might seem like a bit of a no-brainer but I just thought it would be useful to try and find out what could potentially be going on and provide evidence of what I have already tried to do.
When I changed the Adafruit_Arcada arcada; to Adafruit_SPITFT arcada; (thinking this could potentially resolve the issue because within the Adafruit_Arcada.h file there is a class called Adafruit_SPITFT and notAdafruit_Arcada`), this brought up another error which was the following:
simpletest:2:17: error: no matching function for call to 'Adafruit_SPITFT::Adafruit_SPITFT()'

The Adafruit_Arcada class is defined in Boards/Adafruit_Arcada_PyGamer.h and inherits from the Adafruit_Arcada_SPITFT class. I guess there are specific versions of the class for each board.

@chrisl So what classes would I need to mention within my code in order for it to work?

There are some instructions at:
Pygamer setup
That need to be followed in order to permit the Arduino IDE to work with the Pygamer.  It's not clear that you have followed any or all of these instructions.
I recommend that you carefully follow ALL the steps and then start with the simple example to test that you are building and uploading properly.
Then move on to the Adafruit example that uses the Arcada library.

So what I have done is followed all of the instructions in the link sent and the board not has its own serial COM port and does work with a very basic blink example program which does not include any libraries at all. the error to do with Adafruit_Arcada' does not name a type;. The next problem occuring is that now another error message is coming up within the code which I am not too sure it is trying to say:

Arduino\libraries\Adafruit_EPD\src\Adafruit_EPD.cpp: In member function 'void Adafruit_EPD::csHigh()':
and                                                        libraries\Adafruit_EPD\src\Adafruit_EPD.cpp:649:12: error: 'class Adafruit_SPIDevice' has no member named 'endTransaction'.

Something is telling me that something is either out of date or I might have potentially installed something wrong because in the guide that was sent there is 5 examples within the adafruit arcada library. But with the one I have installed, there is lots of examples. The guide itself was not updated too long ago. The arcada library I have installed is the one installed from the library manger and the version of the library is 2.5.0. Perhaps the library is too update to date compared to the one in the guide which potentially might be more out of date.