text:
Error saving SPIFFS on ESP8266 - only after 3rd entry
EDIT1 - This phenomena occurs only after reboot using button or ESP.reboot()
I'll try to make my question more focused:

I have library that saved log events to SPIFFS.

From 3rd entry (in the following example - epoch clock entries), it saves wrongly somehow (jump to Take-4 below).

Following code is an example using only relevant functions from that library.

Quick explanation:
T is holding epoch clock, that stores it right after boot.
write(const char *message, bool NOW) function - gets a message to store, and a boolean NOW if it has to be saved immediately rather than delayed save (delayed saved is implemented only in library, while here it gets saved instantly.)
void _write2file() writes the buffer to SPIFFS.
int getnumlines() returns number of entries saved (seeking for _EOL chars). In code below it acts as information only that serves displaying the problem, while when used in real library code, it limits the number of entries of the log.
void rawPrintfile() prints in human readable manner log's contents.
And last, the only function which does not belong to the library, void insert_log_entry(), simply enter a log entry (always the same one, after reboot).
Take 1-After uploading the sketch, you get this result on:
19:58:00.125 -> add buffer #0: 1234567890

19:58:00.191 -> total Lines before: 0
19:58:00.191 -> entries in buffer: 1
19:58:00.257 -> ~~~ Saved in /logfile.txt ~~~
19:58:00.257 -> row #0 {1234567890}
19:58:00.257 -> ~~~ EOF ~~~

Explanation: there was 1 entry to buffer, no- entries before, and a printout of file contents. So far- OK!
Take 2 - Pressing reboot button, and results are:
19:58:07.747 -> Start!
19:58:07.814 -> add buffer #0: 1234567890

19:58:07.814 -> total Lines before: 1
19:58:07.814 -> entries in buffer: 1
19:58:07.814 -> ~~~ Saved in /logfile.txt ~~~
19:58:07.814 -> row #0 {1234567890}
19:58:07.814 -> row #1 {1234567890}
19:58:07.814 -> ~~~ EOF ~~~

Explanation:again 1 entry in buffer, 1 entry in log, and a printout of 2 entries.
Take 3
Pressing reboot button again, and results are:
19:58:10.167 -> Start!
19:58:10.200 -> add buffer #0: 1234567890

19:58:10.200 -> total Lines before: 2
19:58:10.233 -> entries in buffer: 1
19:58:10.233 -> ~~~ Saved in /logfile.txt ~~~
19:58:10.233 -> row #0 {1234567890}
19:58:10.233 -> row #1 {1234567890}
19:58:10.233 -> row #2 {1234567890}
19:58:10.233 -> ~~~ EOF ~~~

Explanation: same, but now 3 entries are saved.
Take 4!!!
19:58:11.194 -> Start!
19:58:11.227 -> add buffer #0: 1234567890

19:58:11.227 -> total Lines before: 2
19:58:11.260 -> entries in buffer: 1
19:58:11.260 -> ~~~ Saved in /logfile.txt ~~~
19:58:11.260 -> row #0 {1234567890}
19:58:11.260 -> row #1 {1234567890}
19:58:11.260 -> row #2 {12345678⸮⸮⸮1234567890}
19:58:11.260 -> ~~~ EOF ~~~

Explanation: Now here is the unsolved error- 4th entry gets mixed up with 3rd, causing it to count only 2 entries (where it had to be 3), and row #2 is now mixed.
In purpose - I simplified the code to focus on the problem itself, which I can't find it root cause for this error (rather that showing entire library , consisting delayed save and delete line function, when log gets full).
`
#include <FS.h>
unsigned long T = 1234567890;

char *_logfilename = "/logfile.txt";
int _buff_i = 0;
#define TEMP_LOG_SIZE 10
#define TEMP_LOG_LEN 150
int _logSize = TEMP_LOG_SIZE;                 // entries
int _logLength = TEMP_LOG_LEN;                // chars in each entry
char _logBuffer[TEMP_LOG_SIZE][TEMP_LOG_LEN]; // Temp buffer for delayed write
const char _EOL = '\r';
unsigned long lastUpdate = 0;

void insert_log_entry()
{
  char a[25];
  sprintf(a, "%d", T);
  write(a, true);
}
void rawPrintfile()
{
  int row_counter = 0;
  bool new_line = true;

  File file = SPIFFS.open(_logfilename, "r");
  if (!file)
  {

    Serial.println("Failed to open file for reading");
  }
  Serial.print("~~~ Saved in ");
  Serial.print(_logfilename);
  Serial.println(" ~~~");
  while (file.available())
  {
    if (new_line)
    {
      Serial.print("row #");
      Serial.print(row_counter++);
      Serial.print(" {");
      new_line = false;
    }
    char tt = file.read();
    if (tt == _EOL)
    {
      new_line = true;
      Serial.println("}");
    }
    else
    {
      Serial.print(tt);
    }
  }
  file.close();
  Serial.println("~~~ EOF ~~~");
}
int getnumlines()
{
  int row_counter = 0;

  File file = SPIFFS.open(_logfilename, "r");
  if (file)
  {
    while (file.available())
    {
      char tt = file.read();
      if (tt == _EOL)
      {
        row_counter++;
      }
    }
  }
  file.close();
  return row_counter;
}
void write(const char *message, bool NOW)
{
  sprintf(_logBuffer[_buff_i], "%s%c", message, _EOL);

  Serial.print("add buffer #");
  Serial.print(_buff_i);
  Serial.print(": ");
  Serial.println(_logBuffer[_buff_i]);
  _buff_i++;
  lastUpdate = millis();

  if (NOW == true)
  {
    _write2file();
  }
}
void _write2file()
{
  int num_lines = getnumlines();
  Serial.print("total Lines before: ");
  Serial.println(num_lines);
  Serial.print("entries in buffer: ");
  Serial.println(_buff_i);

  File file1 = SPIFFS.open(_logfilename, "a");
  if (!file1)
  {
    Serial.println("Failed to open file for appending");
  }
  else
  {
    for (int x = 0; x < _buff_i; x++)
    {
      file1.print(_logBuffer[x]);
    }
    _buff_i = 0;
    lastUpdate = 0;
  }
  file1.close();
}

void setup()
{
  Serial.begin(115200);
  Serial.println("\n\nStart!");
  SPIFFS.begin();
  insert_log_entry();
  rawPrintfile();
}

void loop()
{
  delay(50);
}

Comments are not for extended discussion; this conversation has been moved to chat.

Well , getting to answer was complicated.

It happens only after reboot ( button, or ESP.reset() ), somehow after 2nd attempt, every time - getting this ( see THIS):

19:58:11.194 -> Start!
19:58:11.227 -> add buffer #0: 1234567890

19:58:11.227 -> total Lines before: 2
19:58:11.260 -> entries in buffer: 1
19:58:11.260 -> ~~~ Saved in /logfile.txt ~~~
19:58:11.260 -> row #0 {1234567890}
19:58:11.260 -> row #1 {1234567890}
19:58:11.260 -> row #2 {12345678⸮⸮⸮1234567890}   <----- THIS ----
19:58:11.260 -> ~~~ EOF ~~~

@Peter, in comments referred for github issue , that pointed out that there is a known problem regarding reboots and validity of data stored. Issue was solved by using file.flush() - but this solution did not solve the problem

When searching ESP8266 core, it pointed out an erros SPIFFS- regarding data saved and it validity

only after updating LittleFS for all instances in code (somehow when checked as part of Peter's suggestion, only few instances were changed from SPIFFS ), solved that problem. no file.flush() or delay() is required.


text:
Control output of XL6009 Boost converter with Arduino
I wonder if someone could help me with figuring out how to control XL6009 Boost converter via Arduino. I have this popular board, and it has potentiometer to adjust the output voltage. However, I want to adjust output voltage based on sensor reading so I need to do it "non-mechanically".
I tried with PWM voltage to the resistor network, but I didn't get wanted results. Any ideas (except digipot)?
Best regards

you posted your question in the wrong place ... this site is for questions about the Arduino

I didn't get wanted results is meaningless ... it does not describe the observed behavior

And why are you excluding digipots? Most Arduinos don't have a DAC, so you would need extra parts anyway

injecting a buffered (low pass, unity gain) voltage into the wiper of the pot didn't work? It works for me. You might not have enough current being injected. No more than a 1k resistor between opamp and wiper. You can also PWM+smooth to feed an optoisolator (or CDS varistor glued to an LED) that call pull one half of the pot down/up. Digipots won't work here, don't even bother.

Thanks for your responses. When I said I didnt get wanted results with resistor network, voltage range to control was too narrow (e.g 22-24V). But here is useful guide https://www.fischl.de/dcdccontrol/. When I changed resistor values a bit, it worked as intended

source: Stack Exchange

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

sort: votes


text:
OTA over MQTT for ESP32
Before starting working, I am just researching around how can I achieve OTA over MQTT in ESP32 in using Arduino IDE.
The process I understand the esp listen to MQTT messages and then received that file over MQTT(not fully at once may be in chunks). And then stored that in flash at specific address. And then change boot loader configuration for executing new firmware.
Here I am confused how can I change boot loader configuration settings to execute the new firmware memory address ??
Any help is appreciated.
is there any out of box library available for this work? Please share reference. I can take reference from there.
Thanks

Everything is done for you using the Update library. Just feed it the right data.

@Majenko I am looking in to that will keep you posted. Thanks

@Majenko I hope Update library can be used with FreeRTOS as well.

the Update library is part of the esp32 Arduino boards support package by Espressif

I am not familiar with OTA for ESP32 but with SAMD21 using ArduinoOTA library and there the download is not done over MQTT but HTTPS.
Link to download is sent over MQTT but that's where it ends, download over HTTPS, verification of received data using checksum and bytes count and once InternalStorage.apply() executed it swaps the program downloaded with the older version and reboot.
EDIT:
As per Juraj request, I am adding the code as a guide you can use to get ideas. You can't run it as is, you would need to add variable declaration and wrap it in a function.
As updating wrong file will most likely brick your board, I would just add that before running this code I check the filename to make sure it is the correct BIN for the board downloading it, I am using constants like WIFI, GSM, and board name and expect to see them in the filename.
I also send the file length from the server as part of the MQTT update request and check it against my own bytes count and I am not relying on TCP to provide an error on corrupted data and do a my own checksum test.
#include <ArduinoOTA.h>  // https://github.com/jandrassy/ArduinoOTA

// Access the file
HttpClient client(*transport, upgradeServer, upgradePort);
client.get(upgradePath);

int statusCode = client.responseStatusCode();
  /*
   0   HTTP_SUCCESS
  -1  HTTP_ERROR_CONNECTION_FAILED  The end of the headers has been reached.  This consumes the '\n' Could not connect to the server
  -2  HTTP_ERROR_API                This call was made when the HttpClient class wasn't expecting it to be called.
                                    Usually indicates your code is using the class incorrectly
  -3  HTTP_ERROR_TIMED_OUT          Spent too long waiting for a reply
  -4  HTTP_ERROR_INVALID_RESPONSE   The response from the server is invalid, is it definitely an HTTP server?
  */

if (statusCode != 200) {
  client.stop();
  // here you can do something with statusCode like notifying over MQTT
}

long length = client.contentLength();
if (length == HttpClient::kNoContentLengthHeader) {
  client.stop();
  //Server didn't provide Content-length header, abort.
  return;
}

if (!InternalStorage.open(length)) {
  client.stop();
  // Not enough space to store the file, abort.
  return;
}

// Start update, length holds the file size in bytes

client.setTimeout(5000);
byte b;
bool ok;
long fileLength = length;
unsigned long otaStartMillis = millis();
int localChecksum = 0;

while (length > 0) {

  ok = client.readBytes(&b, 1);
  if (!ok) {
   // Abort, stopped after ((millis() - otaStartMillis)/1000) Sec
    return;
  }

  InternalStorage.write(b);
  int bValue = (int)b;
  localChecksum = localChecksum + bValue;

  length--;
}

InternalStorage.close();
client.stop();

if (localChecksum != remoteCkecksum) {
 // Checksum mismatch, abort.
  return;
}

if (length > 0) {
  // Timeout at byte length, abort.
  return;
}

InternalStorage.apply(); // this doesn't return, board should restart

Serial.println("Update failed"); //shown only if update failed

Another opportunity to thank Jurak for this library!

In my case, the ESP32 doesn't have access to public network. So I will prefer to send the file over MQTT from server side and client(ESP 32) will receive that and do the required things.

@Abhishekbhatia, how does the ESP32 do MQTT without access to the server?

@Juraj I mentioned that, In my use case ESP 32 doesn't have access to public network. It is connect to MQTT server hosted on edge device(They are on private network) . I just don't wanted to use http.

@Juraj would you suggest me which library is better to use for my use case ArduinoOTA or update ??

@Abhishekbhatia Update. because esp32 boards support package has a libray named ArduinoOTA. you would have to delete it to use the generic ArduinoOTA. The  generic ArduinoOTA only wraps the Update library. Generic ArduinoOTA is useful for esp32 with W5500 or enc28j60 Ethernet module.

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


text:
Fastest external High Speed ADC?
I am in a situation close to:
Hi-speed external ADC
But with 100,000 ~ 500,000 samples per second, I don't need more.
I only want to detect changes in 2 sensors, so each loop is only an "analogread" and a couple of conditionals, so I have the 16MHz almost intact to store data from an external ADC.
What is the fastest thing you can aspire to with an arduino and an external ADC?

The link you gave explains the problem with an external ADC:  No matter how fast the ADC is, the Arduino has to get the data somehow, and put it someplace.  You can go faster than analogRead, but 100 kHz is about the limit for a single channel (8 bits, 2MHz clock) in bursts of 1024 samples, or just under 50 kHz with 2 channels. What exactly are you doing?  Can you use digital instead of analog?  Direct read of 8 digital pins can run at over 400 kHz in 1024-byte bursts.

Thanks @Boggyman, I have 2 analog photodiodes, and I want to detect any change in the fastest possible way. With 8 bits, or either 6, it's enough. But I can not find an external ADC with this characteristics. (that can be bought at a reasonable price)

Just browsing through the Mouser catalog brings up the following: MAX153, 1MSps, 8 bit parallel output with prices from about $8 or the TI ADC0820, 667KSps, 8 bit parallel with prices starting at about $5.

The Arduino as only one ADC. So it can't read 2 "A input" at exact same time. So internaly it's done by multiplexing. I suggest to start having at MOZZI Lib. It's a lib for creating musical instrument on Arduino and the LIB has it's own analogRead() function, faster than the original one.

Thanks @StarCat, I'm going to buy MAX153 and test it.

You mention detecting changes.  Depending on exactly what you are doing, there are ways of doing that externally without an ADC.  For example, if you want to know when the difference between the sensors exceeds a certain threshold, you can use a differential amplifier followed by a threshold comparator.  That gives you a pure digital signal that you can detect very quickly, or better yet use to generate an interrupt.

Thanks @Boggyman, I have connected the sensor output to a comparator and this to a digital pin. Now I am investigating if I can get more precision than the micros function offers.

If you explain exactly what you are doing in more detail, we can better help you find a solution.  If you are still at the stage of investigating what's going on, you may want to try my DaquinOscope https://www.daqarta.com/dw_rroo.htm.  It runs under Daqarta, but it's all FREE for Arduino users. It can sample at the speeds I mentioned in my first comment, and show traces of 1024 samples each on your computer screen.


text:
2.4" TFT LCD is only showing white screen, but the touch functions still work
Hi (Sorry for the long post).
The other day I finally found a code that worked on my standard 2.8" TFT LCD by Simkeim, but then I pressed the bottom left corner too hard and the screen went white. The code is a calculator code and it worked because the screen showed the numbers and the screen saver, but when I pressed the screen nothing happened. After the screen went white, I "opened" it and saw no damage to the screen. I have tried a bunch of example sketches and now the touch functions work, but nothing is displayed on the screen. The LCD does not have any wires, it just plugs in the board. When I upload a sketch, the backlight changes brightness a bit, and there is a slight line on the left side of the screen, when the code uses dark colors, I can press two parts of the screen and the screen goes dark (except for a small part of the left side).
Could the screen be damaged by pressure?
This is what the LCD looks like:

It's dead, Jim.

what do you mean by opened it?

I just took the top part of the LCD off to see the screen, and it had no damage.

but then I pressed the bottom left corner too hard and the screen went white. Meh. It should be quite obvious what happened to it.


text:
Adafruit TFT 1.3 inch display with arduino-rotate the font
I am using Arduino MKR1500 with adafruit 1.3 inch display(https://www.adafruit.com/product/4313) and I want to rotate the font on the screen by 90 degree. I tried setRotation() and added an angle in the brackets. but that did not help.
Can someone please let me know what command do I need to use to do that?

setRotation usually takes a number 0-3 for 90 degree steps

Hi Majenko, I tried setting it up to 0,1,2 in void setup() none of them changed the display setting . Is there something I could be missing?

Sorry, I figured it out. I was supposed to configure that in void tftPrintTest().


text:
ADC stops working at small delays (MCP3464)
I have tried debugging for a couple days with no luck, so this question is a cry for help.
I am trying to configure an external ADC (MCP3464 datasheet). The ADC uses SPI communication and I am getting a response from it when I set the delay to 1000ms. If I lower this below 100ms, the ADC does not update and prints the last value stored in the ADC register.
Here is the relevant part of the code, although I have attached the whole file in case you would like to check command bytes etc.
void adcSimple(){

    unsigned char convStatus;
    uint16_t adcData;
    // chip Select pin LOW to read/write to ADC
    digitalWrite(adcChipSelectPin,LOW);
    convStatus = SPI.transfer(readConversionData);
    // extracts remaing bytes and append to adcData 16 bit integer (15bits plus sign)
    adcData = SPI.transfer(0);
    adcData <<= 8;
    adcData |= SPI.transfer(0);
    // chip select pin hgih to stop read/write to ADC
    digitalWrite(adcChipSelectPin, HIGH);

    // start next conversion
    writeData(&startConversionFastCmd, 1);

    Serial.println(adcData);
}

void setup(){
  Serial.begin(115200);
  while (! Serial);
  spiInit();
  adcInit();
  // set ADC Multiplexer to channel 0
  writeData(&muxRegisters[0][0], 2);
  delay(1000);
}

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

The adcSimple() function reads the ADC register address and appends it to the 16 bit adcData variable.
writeData(&startConversionFastCmd, 1);

The line above then restarts the ADC conversion (not the whole device) which is required to update the ADC register. For some reason this does not update the ADC register when there is insufficient delay in the loop.
  // Check the data ready bit
  if ((convStatus & 0x04) == 0x04)
  {
     Serial.println("ADC not ready!!!");

  }

I have run a test on convStatus, and this shows the ADC is not ready when the delay is short (around 100ms). I just don't understand why it takes so long (1000ms is equivalent to light years when running on 6MHz clock!)
Any suggestions would be greatly appreciated. Maybe someone has had a similar problem before?
Thanks,
Will

"attached the whole file", I seem to have missed it.  Where does writeData come from?  Or adcInit?

SOLVED: I lowered the oversampling rate (See table 5-6 of datasheet) and thus increased the data rate. Thanks for the response timemage

No problem. Unfortunately now you have an unanswered question that's unlikely to be answered.  If you wanted, you could flesh-out your answer-in-comment and post it as an answer proper.  With only your own answer, you have some latitude, in my opinion anyway, in editing the question to match.  Basically, you can leave behind a useful question/answer combo for a future reader with an Arduino and an MCP3464.

Can you please share the file because I'm facing writing and reading register for the same adc.
Also I'm not able to confirm that spi is initialized or not

I have added the MCP3464 library/driver to github - https://github.com/WillPowellUk/MCP3464-ADC


text:
Where is the Arduino IDE boards.txt file for Nano Every located?
My Arduino Nano Every runs at 16Mhz (but the 4809 can support internal 20Mhz).
I know it may be possible to alter the boards.txt file and set it to build for 20Mhz.
However, I can't find the boards.txt for these new boards (MegaAVR).
Where is the boards.txt located?

I found the boards.txt file at: ~/.arduino15/packages/arduino/hardware/megaavr/1.8.7
The Nano Every portion of the boards.txt looks like the following:
##############################################################

nona4809.name=Arduino Nano Every

nona4809.vid.0=0x2341
nona4809.pid.0=0x0058

nona4809.upload.tool=avrdude
nona4809.upload.protocol=jtag2updi
nona4809.upload.maximum_size=49152
nona4809.upload.maximum_data_size=6144
nona4809.upload.speed=115200
nona4809.upload.use_1200bps_touch=true
nona4809.upload.extra_params=-P{serial.port}

nona4809.build.mcu=atmega4809
nona4809.build.f_cpu=16000000L
nona4809.build.board=AVR_NANO_EVERY
nona4809.build.core=arduino
nona4809.build.variant=nona4809
nona4809.build.text_section_start=.text=0x0
nona4809.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3 -DNO_EXTERNAL_I2C_PULLUP
#nona4809.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu}

nona4809.bootloader.tool=avrdude
nona4809.bootloader.file=atmega4809_uart_bl.hex
nona4809.bootloader.SYSCFG0=0xC9
nona4809.bootloader.BOOTEND=0x00
nona4809.bootloader.OSCCFG=0x01
nona4809.fuses.file=fuses_4809.bin

menu.mode=Registers emulation
nona4809.menu.mode.on=ATMEGA328
nona4809.menu.mode.on.build.328emulation=-DAVR_NANO_4809_328MODE
nona4809.menu.mode.off=None (ATMEGA4809)
nona4809.menu.mode.off.build.328emulation=

##############################################################

If you change the following line from:
nona4809.build.f_cpu=16000000L

to:
nona4809.build.f_cpu=20000000L

Then go in and turn on verbose when you build in the Arduino IDE you will see that avrdude will pass in the following when it builds your sketch:
DF_CPU=20000000L

Will this push the CPU to 20Mhz?  Not sure, but at least you know where this is now.
UPDATE
FYI - Do not set your board to 20Mhz.  Especially if you have Serial Communication going on.  I have software serial set up to communicate with an attached bluetooth device and when you set the CPU to 20Mhz other things are not set properly and the Serial communication fails.

If the intention is to run the Nano Every at 20 MHz, you're probably better off using MCUdude MegaCoreX.

@timemage Very good point. I'm doing some different things.  Using Nano Every board as a prototype. Then, I'm building the HEX file in a Arduino IDE & exporting it.  I then upload it to a raw 40-pin ATMega4089 using Atmel-ICE programmer & Microchip studio.
My 4089 runs on the 20Mhz internal crystal & I was trying to see if I could get Arduino IDE to generate a HEX that is using 20Mhz.  Thanks again for the link

why not upload directly to ATmega?

In addition to set the
nona4809.build.f_cpu=20000000L

you will have to set the corresponding fuse byte to
nona4809.bootloader.OSCCFG=0x02

this enables the 20 MHz clock.


text:
Connecting an LCD when Pins A4 and A5 are Occupied
Recently I've been working on an automatic dog feeder dispenser (that dispenses by turning a screw attached to a stepper motor). Currently I have a Nema 17 connected to an L298N stepper driver which is connected to Arduino pins 9-12 and a DS1307 RTC connected to analog pins A4 and A5 (I would have a picture but the wiring is all over the place). I would like to connect a 16x2 LCD screen (with a potentiometer already on the back and 4 connecting pins) but from everything I've seen online, it also uses analog pins A4 and A5 which are occupied by the RTC. How would I go about connecting the LCD?
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <RTClib.h>
#include <SoftwareSerial.h>
#include <Stepper.h>

RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x3F , 16 , 2);
Stepper myStepper(200 , 9 , 10 , 11 , 12);

void setup() {
  lcd.init();
  lcd.print("yes");
  Wire.begin();
  Serial.begin(9600);
  rtc.adjust(DateTime(2021 , 7 , 15 , 3 , 23 , 0));
  myStepper.setSpeed(100);
}

void loop() {
  DateTime now = rtc.now();
  Serial.print(now.hour());
  Serial.print(":");
  Serial.print(now.minute());
  Serial.print(":");
  Serial.print(now.second());
  Serial.println(" ");

  lcd.print(now.hour());
  lcd.print(":");
  lcd.print(now.minute());
  lcd.print(":");
  lcd.print(now.second());
  lcd.println(" ");

  if ((now.hour() == 7 and now.minute() == 0 and now.second() == 0)) {
    myStepper.step(1000);

}
  delay(1000);

}

I2C communication lines support more than one device on the same pins, so just connect
the LCD to the same pins... or you could just look under your Arduino to locate the 2 more I2C pins(Left of the Aref pin)

https://www.arduino.cc/en/Reference/Wire

I connected both the LCD and RTC to A4 and A5 via a breadboard and it works great. Thanks!

Here is one example where LCD and RTC both are conencted to same I2C pins. https://wokwi.com/arduino/projects/306828496357818944

As mentioned in the comments: Your LCD and the RTC both use the I2C bus for communication. That bus is designed to have many devices simultaneously connected. For this to work every slave device on the bus (the Arduino is the master device, which has no address) has to have a unique address. In your code you write, that the LCD is on address 0x3F. The RTC DS1307 is 0b1101000 or 0x68 (same value in binary or hexadecimal representation) (see the DS1307 datasheet, page 12).
So you can connect  both devices to the same pins, as the communication interface there already supports that. The pins A4 and A5 are the I2C pins of the Arduino, so you need to connect them there for using the Arduinos I2C hardware.

Here are my 2 cents.
As the other answer suggests, you can always use the same I2C lines for devices. The devices will be differentiated via an I2C address. I have compiled one example based on your code. Here is the link to the simulation
The code is below
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include <RTClib.h>

RTC_DS1307 rtc;

LiquidCrystal_I2C lcd(0x27, 16, 2);

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

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

  lcd.init();
  lcd.backlight();
  lcd.print("yes");
}

void loop() {
  DateTime now = rtc.now();
  Serial.print(now.hour());
  Serial.print(":");
  Serial.print(now.minute());
  Serial.print(":");
  Serial.print(now.second());
  Serial.println(" ");

  lcd.setCursor( 0,0);
  lcd.print(now.hour());
  lcd.print(":");
  lcd.print(now.minute());
  lcd.print(":");
  lcd.print(now.second());

  if ((now.hour() == 7 and now.minute() == 0 and now.second() == 0)) {
    // myStepper.step(1000);
  }

  delay(1000);
}

As you can see, I2C lines are shared between the RTC module and the LC display module.


text:
Arduino UNO voltage supply reduces when I add more sensors
I have an Arduino UNO. When I connect an MQ-9 sensor or an ESP8266MOD WiFi chip, the LCD backlight drops that it doesn't display anything, the red LEDs on the Arduino board dims, and the voltage regulator begins to get hot.
I am using a 12V -- 1.5A DC supply to power the Arduino as the USB port only works for uploading sketches, it doesn't even power the Arduino when nothing is connected. What could be wrong?
NOTE: When I unplug the gas sensor, the Arduino board LEDs get brighter and the LCD too, it works fine with some other sensors like an LM35 or a flame sensor.

You are overloading the Arduinos voltage regulator.
The Arduino uses a linear voltage regulator, which dissipates the excess voltages as heat.The higher the provided voltage, the lesser current you can draw from it (since it can only handle a specific power dissipation without a heatsink and power is voltage * current). If you have a genuine Arduino, the voltage regulator will go into thermal emergency shutdown, if you completely overload it. Most Arduino clones use a cheaper regulator, which will just burn out and possibly destroy the Arduino.
So if you require quite an amount of current (like the MQ-9 due to its heating element), you should buy an extra voltage regulator, in best case a switching "buck" regulator (since they are way more efficient than linear regulators). For example there are many rather cheap boards with a switching regulator, which take 12V and output a variable voltage controlled via a small potentiometer (which you can trim for 5V output).

the USB port only works for uploading sketches, it doesn't even power the arduino when nothing is connected.

Then most likely you have already overloaded the diode, that is in the USB power path (for protecting the PCs USB port and helping with supply voltage selection). If the diode were fried and failed open, then the connection from USB positive power to 5V rail on the Arduino is no longer there. A genuine Arduino Uno should also have a polyfuse in the USB line, which can save you from drawing too much current. It should connect again, after you removed the devices, that draw too much power.

Note that the Arduino Uno Rev 3 does not have a protection diode in the path of the USB, only a polyfuse and a mosfet controlled by an op-amp, which activates the mosfet if VIN is below 7V

The MQ-9 has a heating preparation cycle that draws more than a third of a watt which is more power than the Arduino can supply via a pin if I remember correctly. Have you taken that into allowance? You can design the heater power to be triggered by the Arduino without overloading the pin (e.g, using a transistor).
See https://electronics.stackexchange.com/questions/67092/how-much-current-can-i-draw-from-the-arduinos-pins
If your circuit already allows for the above it could also be a bad/shorted sensor? You could test it’s resistance with a multimeter and compare it to the data sheet.

I guess OP uses a sensor module which is powered from 5 V pin

I think your guess is right. Chrisl’s is a much better answer.

You are using a lot more power than an arduino pin can supply. The gas sensor takes a lot of power which the arduino's pin supply of 5v and 200mA MAX cannot tolerate. So I would suggest you power the gas sensor using ur 12v Powersupply by creating a simple potential divider, using a buck converter or simply one of those cheap 7805 regulators. For any other power related queries you can refer this excellent article by BILL from Dronebot Workshop. Good Luck!!


text:
No communication between two stations that include Arduino Nano and nRF24L01
I'm struggling to establish a link between two Arduino Nano using nRF24L01 (the module that contains PA and LNA). I assume I made a coding mistake (May be in the setup method?), and I need help in finding it.
I’m using the gettingStarted example from the TMRh20 V1.4.1 RF24 library, with slight modifications in the addressing and error messaging. The sketch contains the code for both the transmitter and the receiver, and the selection is done by the ROLE flag in compile time.
Hardware:

I'm using home-designed PCB. For this setup only the Arduino and RF24 modules are assembled.
Power:
a.    The RF24 is fed by the 3.3V output of the Arduino.
b.    There is a 47uF cap to filter the power.
c.    The power traces length is about 20mm, and 1.2 mm thick of 1oz copper.
Measurements
a.    The setup method verifies that the RF24 module is connected to the SPI bus and reacts to the commands. I verified this test by removing and inserting a module. It works.
b.    When the transmitter was running at repetition rate of 1 cycle per second, I used an oscilloscope to measure on the power line of the RF24 module a ripple of 50mV over DC level of 3.25V (per the data sheet the minimum supply voltage is 1.9V).
The setup method verifies explicitly that the RF24 module is connected to the SPI bus and reacts to the commands.

Debugging:

To begin with, the message ** “Transmission failed or timed out” **
was issued.
When I added the line “radio.setAutoAck(false)” to the setup method, the error message was changed into ** “Transmission succeeded; retransmission failed” **. This is odd because I had to explicitly specify a mode that the chip should be in by default.
I replaced both module in both sides to brand new units, to no avail.
I added to the library’s ** write ** function a print of the status register. It reflects transmission success (see below).

Currently the transmitter messages are as follows (the line numbers were added for the notes):
1   Start loop - TX station
2   WRITE TP 3 - TX OK: status=2E
3   Time to transmit = 960 us.
4   Transmission succeeded; transmitted: 0.08
5   Back transmission failed
Notes:

Lines 1, 3, 4 and 5 are issued by the main loop.
Line 2 is the WRITE printout.
a.  Bit 5 of the status is the TX_DS flag, which signify that the TX FIFO status. Active means that the packet was transmitted successfully.
b.  Bits 3:1 mean that RX FIFO is empty.
Line 4 – printout of the transmitted payload. The number is increased in every loop by 0.01.
Lines 5 tells us that the nothing was received from the other side (the receiver reports that he received nothing).

My problem is that either the transmitter doesn't transmit (low probability) or there is a mismatch between the stations. I assume I made a coding mistake (May be in the setup method?), and I’d appreciate any help in finding it.
Or, should I add voltage regulator to increase the 3.25V to 3.3V?
    #include <SPI.h>
#include "RF24.h"
// instantiate an object for the nRF24L01 transceiver
RF24 radio(9, 10);           // using pin 9 for CE, pin 10 for CSN
uint32_t address[2] = {0x123456, 0x654321};
byte role = 1;
float payload = 0.0;
uint16_t counter = 0;
int terminationTimer;
/***********************************************************/
void setup()
{
  Serial.begin(9600);
  while (!Serial) ;
  Serial.println("Starting...");

// initialize the transceiver on the SPI bus
  radio.begin();
// Modification - the installed library doesn't
// return flag. Instead, check the SPI bus by
// changing register contents
  radio.setPALevel(RF24_PA_HIGH);        // RF24_PA_MAX is default.
  bool paError = !radio.isChipConnected() | (radio.getPALevel() != RF24_PA_HIGH);
  radio.setPALevel(RF24_PA_MIN);
  paError |= (radio.getPALevel() != RF24_PA_MIN);
  if(paError)
  {
    Serial.println("Radio HW error");
    while (true) ;                // Halt
  }
  Serial.print("radio role = ");
  Serial.println(role);
  radio.setRetries(15,15);
  radio.setAutoAck(false);

  if(role == 1)
  {
    radio.openWritingPipe(address[1]);    // always uses pipe 0
    radio.openReadingPipe(1, address[0]); // pipe 1 for
    radio.stopListening();                // put radio in TX mode
  }
  else
  {
    radio.openWritingPipe(address[0]);    // always uses pipe 0
    radio.openReadingPipe(1, address[1]); // using pipe 1
    radio.startListening();               // put radio in RX mode
  }
  terminationTimer = millis();
//Serial.println("TP C");
} // setup
/****************************************************************/
void loop()
{
//Serial.println("TP D - start loop; role = " + String(role));
//delay(1000);
  if (role == 1)
  {
Serial.println("\nStart loop - TX station");
 // This device is a TX node
    unsigned long start_timer = micros();            // start the timer
    bool report = radio.write(&payload, sizeof(float)); // transmit & save the result
    uint32_t end_timer = micros();              // end the timer
    if (report)
    {
// All the code in this block is designed for testing only
      Serial.print(("Time to transmit = "));
      Serial.print(end_timer - start_timer); // print the timer
      Serial.println((" us."));
      radio.startListening();               // put radio in RX mode
      Serial.print("Transmission succeeded; transmitted: ");
      Serial.println(String(payload));
      Serial.print("Back transmission ");
      int tDelay = millis();
      while(((millis() - tDelay) < 250) && !radio.available()){}
      if(radio.available())
      {
        float pl;
        radio.read(&pl, sizeof(float));  // fetch payload from FIFO
        Serial.print("succeeded. Retransmitted: ");
        Serial.println(pl);
      }
      else
        Serial.println("failed");
      radio.stopListening();             // put radio in TX mode
      payload += 0.01;                   // increment float payload
    }
    else Serial.println(("Transmission failed or timed out")); // payload was not delivered
// to make this example readable in the serial monitor
    delay(1000);  // slow transmissions down to 1 per second
  }
  else
  {
Serial.println("\nStart loop - RX station");
// This device is a RX node
    uint8_t pipe = 0;
    if (radio.available(/*&pipe*/))   // is there a payload? get the pipe number that recieved it
    {
      uint8_t bytes;
      bytes = sizeof(float);         // get the size of the payload
      radio.read(&payload, bytes);   // fetch payload from FIFO
// The rest of the code in this block is for debugging
      radio.stopListening();          // put radio in TX mode
      delay(10);
      Serial.print("Received ");
      Serial.print(bytes);          // print the size of the payload
      Serial.print((" bytes on pipe "));
      Serial.print(pipe);             // print the pipe number
      Serial.print((": "));
      Serial.print(payload);
      if(radio.write(&payload, bytes))
        Serial.print("; back transmission succeeded.");
      else
        Serial.println("; back transmission failed");
      radio.startListening();          // put radio in RX mode
    }
    else
    {
      Serial.println("no receive");
      delay(700);
    }
  } // role
/*
  if((millis() - terminationTimer) > 10000)
  {
    Serial.println(("Halt"));
      while(true){}
  }
*/
} // loop

I gave up and switched to ESP32


text:
How to send data from one Arduino to another isolated?
I have no experience about serial communications, with that being said; I have two circuits isolated from each other and each have a ATMEGA8 reading a voltage on their ADC.
I want one of them to send ADC data to another without having a common ground. I know that I can do it with a Bluetooth or Wi-Fi "module" but I'm looking for an easier way, like maybe with an optocoupler but again I'm not aware of the limits.

What's the cheapest and simplest way to do this? and basically how it's done?

There's a lot of information about making two Arduinos talk to each other but I couldn't find much information/documentation on isolated communications.

So you still want communication via a wire, but just with isolated grounds? Then yes, the optocoupler is the correct way, one for each UART/Serial line. You can find tutorials on how to use an optocoupler on the web. Do you have any specific questions about it?

@chrisl I'm not lazy, I just couldn't find it. can you please link one of those tutorials on how to use optocouplers for serial communications?

I didn't want to suggest, that you are lazy. I would suggest to read a generic tutorial about optocouplers, not directly involved with UART/Serial. They are pretty simple components, so the general principle is also how they are used for Serial. When you understand how they work and how they are wired you should be able to build them into your Serial path. I guess you searched for tutorials directly with the Serial lines, but there are many tutorials when searching only for optocoupler tutorials.

@chrisl I know how optocouplers works, I just don't know how to implant it as serial communicator.

A few seconds on google images looking for "optoisolator uart" yields a number of possible circuits.

One example: https://github.com/TaaraLabs/OptoIsolatorFTDI/blob/master/OptoIsolatorFTDI-sch.png

@Majenko Thank you.

[Consolidating an answer from the comments]
A wired connection using Optical isolation (aka Optocouplers) is the recommended way to solve this problem.
There are tutorials available online regarding optical isolation (e.g., https://www.electronics-tutorials.ws/blog/optocoupler.html; https://bestengineeringprojects.com/interfacing-optocoupler-with-arduino/).
One (of many) possible example circuit was noted as:

Note that, on this schematic, the pin labeled “RXI” on the left should be connected to one Arduino's TX, whereas the “RXI” on the right should be connected to the other Arduino's RX.


text:
Using MAX30100 SpO2 value to turn on LED
max30100 i2c sensor gives heartrate and spo2 reading in serial and also can show values in lcd display. I want to show it's indication via LED.
If SpO2 value <94 , it will turn on Red led in digital pin 4
If SpO2 value >=94, it will urn on Green led in digital pin 5
Here pox.getSpO2() gives the SpO2 value.
How can I use this value to toggle between two digital pin. I understand it's easier to read analog pin value for toggling but I am searching for guidelines how I2C values can be use for this condition.
Thank you.
Here is the minimalistic code of SpO2
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS     1000

PulseOximeter pox;
uint32_t tsLastReport = 0;

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

    Serial.print("Initializing pulse oximeter..");

    if (!pox.begin()) {
        Serial.println("FAILED");
        for(;;);
    } else {
        Serial.println("SUCCESS");
    }
}

void loop()
{

    pox.update();

    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("SpO2:");
        Serial.print(pox.getSpO2());
        Serial.println("%");

        tsLastReport = millis();
    }
}

You've done all the hard work already by setting the sensor up and managing to read from it.
I'd define a constant for the SpO2 threshold near the top, and convenient names for the pins:
const uint8_t SpO2_threshold = 94;  // percent
const uint8_t red_pin = 4;
const uint8_t green_pin = 5;

Then set the pins to output mode in the setup() as usual. (Maybe set them both HIGH (or LOW) too in there, to indicate that no reading has been done yet.)
In the loop, inside the reporting section, simply grab the value and toggle the pins:
...
uint8_t spo2 = pox.getSpO2();
// Print it out to serial if needed, then:
if (spo2 < SpO2_threshold) {
  digitalWrite(green_pin, LOW);
  digitalWrite(red_pin, HIGH);
} else {
  digitalWrite(red_pin, LOW);
  digitalWrite(green_pin, HIGH);
}

A more involved version that pulses one LED (short on time, variable off time) depending on the value read from the sensor. It uses the same technique as the sensor reading timing (the one used in the "blink without delay" example).
Sensor readings are clamped (any value at or below spo2_min will result in the fasted blink time, over spo2_max the slowest). Then that range is mapped to a range of led off times. Don't use the values in this example, I'm not a medical doctor :-)
// pin mapping
const uint8_t led_pin = LED_BUILTIN;

// sensor readings (%)
const int spo2_min = 85;
const int spo2_max = 100;

// led timings (ms)
const unsigned long led_off_min = 50;
const unsigned long led_off_max = 5000;

unsigned long led_off_time = led_off_max; // variable off time
const unsigned long led_on_time = 50;     // fixed, short on time

// sensor reading timing (ms)
const unsigned long sensor_interval = 1000;

// led state
uint8_t led_state = LOW;

// "timer" state
unsigned long last_reading = 0;
unsigned long last_led_toggle = 0;

void setup() {
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, led_state);

  Serial.begin(9600);

  Serial.print("Initializing pulse oximeter..");
  if (!pox.begin()) {
    Serial.println("FAILED");
    for (;;);
  } else {
    Serial.println("SUCCESS");
  }
}

void loop() {
  pox.update();
  unsigned long current_millis = millis();

  /* sensor reading "timer" */
  if (current_millis - last_reading >= sensor_interval)
  {
    last_reading = current_millis;

    int spo2 = pox.getSpO2();

    // clamp reading to expected range
    int clamped = constrain(spo2, spo2_min, spo2_max);
    // map to off time range
    led_off_time = map(clamped,
                       spo2_min, spo2_max,
                       led_off_min, led_off_max);

    char buff[128];
    sprintf_P(buff, PSTR("reading: %d (%%) -> interval: %lu (ms)"),
              spo2, led_off_time);
    Serial.println(buff);
  }

  /* led toggling "timers" */
  unsigned long led_elapsed = current_millis - last_led_toggle;

  if ((led_state == LOW) && (led_elapsed >= led_off_time))
  {
    last_led_toggle = current_millis;
    led_state = HIGH;
    digitalWrite(led_pin, led_state);
  }
  else if ((led_state == HIGH) && (led_elapsed >= led_on_time))
  {
    last_led_toggle = current_millis;
    led_state = LOW;
    digitalWrite(led_pin, led_state);
  }

}

Thanks a lot. I already tried earlier same as this way and it's working. You explanations made it more clearly understandable to me. Thank you.

Hello, how about using only single red led via giving pulse. If <94, led will blink rapidly. if >=94, led will blink slowly. I tried to add delay(); but it works when using around 10ms delay. but for 500ms delay, spo2 loops also gets delay and it only show 0%. Doesn't work for larger delay cycle. Any thoughts ?

delay is not your friend. Use the same technique as you did for the sensor readings, i.e. check the time elapsed since you last toggled the LED, and toggle it if that is longer than your threshold. Added an example. Probably won't be great if you're only receiving ints in a rather small range - you don't have much granularity.

Other note: if you need need more complicated than this, I'd recommend you find a timer library that you like, and look into state machines also. Lots of examples and docs on both these topics.

Hi, Can't thank you enough. It will take time to understand as I'm not familiar with these term some much. But I want to point out some which i couldn't understand
char buff[128];
sprintf_P(buff, PSTR("reading: %lu (%%) -> interval: %lu (ms)"),
spo2, led_off_time);
Serial.println(buff);
giving this output in serial monitor, when spo2 should show 0%
reading: 3276800 (%) -> interval: 1701969920 (ms)
So, I directly called Serial.print(pox.getSpO2());

Another thing, I wanted to show, when blink slow, "health normal" and when blink fast, :health critical" in serial monitor. First I tried to add in last if else if statement but serial monitor shows both lines.
So, I created another if else statement to show in serial monitor.
Any improvements and thoughts on this?

There was an error in the printf format string, fixed it, but can't reproduce what you are seeing. The only place where the speed changes is in the sensor update part. If you want to print something based on the reading value, it must go in there. If you want to repeat it, then you need to save it so that the last reading is available elsewhere in the loop.


text:
Comparison of a string received from MQTT/Cloud/Arduino
I am trying to compare the string of data which I am receiving from the MQTT broker. If I receive the keyword faster I want to print "increase motor speed" and when I get slower keyword or any other keyword, I want to print "decrease motor speed". I am not sure how to store the data I receive from mqttClient.read()and then store it in string to then compare it
Below is the snippet of the code where I have added it and it seems not to work correctly in my case. can you look at it and let me know what is the mistake?
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
String ipstring= String("(char)mqttClient.read()");
String fast ="faster";
if((char)mqttClient.read()==fast)
{
Serial.println("increase motor speed");}
else
{
Serial.println("decrease motor speed");
}*
}

I have also attached the code for reference.
Thank you!
/*
  Azure IoT Hub NB

  This sketch securely connects to an Azure IoT Hub using MQTT over NB IoT/LTE Cat M1.
  It uses a private key stored in the ATECC508A and a self signed public
  certificate for SSL/TLS authetication.

  It publishes a message every 5 seconds to "devices/{deviceId}/messages/events/" topic
  and subscribes to messages on the "devices/{deviceId}/messages/devicebound/#"
  topic.

  The circuit:
  - MKR NB 1500 board
  - Antenna
  - SIM card with a data plan
  - LiPo battery

  The following tutorial on Arduino Project Hub can be used
  to setup your Azure account and the MKR board:

  https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-nb-1500-to-azure-iot-hub-af6470

  This example code is in the public domain.
*/

#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <utility/ECCX08SelfSignedCert.h>
#include <ArduinoMqttClient.h>
#include <MKRNB.h>

#include "arduino_secrets.h"
int sensorValue;

/////// Enter your sensitive data in arduino_secrets.h
const char pinnumber[]   = SECRET_PINNUMBER;
const char broker[]      = SECRET_BROKER;
String     deviceId      = SECRET_DEVICE_ID;

NB nbAccess;
GPRS gprs;

NBClient      nbClient;            // Used for the TCP socket connection
BearSSLClient sslClient(nbClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  // reconstruct the self signed cert
  ECCX08SelfSignedCert.beginReconstruction(0, 8);
  ECCX08SelfSignedCert.setCommonName(ECCX08.serialNumber());
  ECCX08SelfSignedCert.endReconstruction();

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, ECCX08SelfSignedCert.bytes(), ECCX08SelfSignedCert.length());

  // Set the client id used for MQTT as the device id
  mqttClient.setId(deviceId);

  // Set the username to "<broker>/<device id>/api-version=2018-06-30" and empty password
  String username;

  username += broker;
  username += "/";
  username += deviceId;
  username += "/api-version=2018-06-30";

  mqttClient.setUsernamePassword(username, "");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {
  if (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY) {
    connectNB();
  }

  if (!mqttClient.connected()) {
    // MQTT client is disconnected, connect
    connectMQTT();
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();

  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

unsigned long getTime() {
  // get the current time from the cellular module
  return nbAccess.getTime();
}

void connectNB() {
  Serial.println("Attempting to connect to the cellular network");

  while ((nbAccess.begin(pinnumber) != NB_READY) ||
         (gprs.attachGPRS() != GPRS_READY)) {
    // failed, retry
    Serial.print(".");
    delay(1000);
  }

  Serial.println("You're connected to the cellular network");
  Serial.println();
}

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!mqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    Serial.println(mqttClient.connectError());
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe("devices/" + deviceId + "/messages/devicebound/#");
}

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  mqttClient.beginMessage("devices/" + deviceId + "/messages/events/");
  mqttClient.print("hello ");
  sensorValue = analogRead(A0);
  mqttClient.println(sensorValue);
  //mqttClient.print(millis());

  mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    Serial.print((char)mqttClient.read());
    String ipstring= String("(char)mqttClient.read()");
    String fast ="faster";
    if((char)mqttClient.read()==fast)
    {
      Serial.println("increase motor speed");}
      else
      {
        Serial.println("decrease motor speed");
        }
  }
  Serial.println();

  Serial.println();
}

Comments are not for extended discussion; this conversation has been moved to chat.

As I read the comments, I see the project requirements are evolving. The 0 = Off command structure will severely limit what you can do, but it is a good starting point.
Regarding the first block of code starting with while (mqttClient.available()) {, then adding your one digit / char commands idea, I have this test sketch for you to try.
You don't need the String object to accomplish your goal. You may have to do something like this though  input = (char)mqttClient.read() where the test sketch uses this input = Serial.read();.
char input;

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

void loop(){

  if(Serial.available() > 0){

    input = Serial.read();

    if(input == '0'){
      Serial.println("Turn Off");
    }

    else if(input == '1'){
      Serial.println("Turn On");
    }

    else if(input == '2'){
      Serial.println("Decrease Speed");
    }

    else if(input == '3'){
      Serial.println("Increase Speed");
    }
  }
}

To take it a step further, let's say you want to send commands that start with a single letter, then after the letter, the remaining digits, or chars have a purpose, if you want them to. For example, lets say you send the following command d50. The d could mean decrease speed, and the 50 could mean 50%, 50 steps, etc.
The following test sketch illustrates my point.
char inputBuffer[64 + 1];

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

void loop(){

  while(Serial.available() > 0){

    Serial.readBytesUntil('\n', inputBuffer, sizeof(inputBuffer));

    if(inputBuffer[0] == 'f'){
      Serial.println("Letter 'f' entered");
    }

    // Letter "r". Everything after the "r" should be digits.
    else if(inputBuffer[0] == 'r'){
      Serial.print("Letter 'r' entered\t");
      // Change the letter "r" to the digit 0 to keep atol() happy.
      inputBuffer[0] = B110000;
      Serial.print("Number entered = ");
      Serial.println(atol(inputBuffer));

      // Your code here that uses the number parsed using atol().

    }

    // Letter "s". Everything after the "s" should have a max
    // length of up to 64 chars long for a 64 + 1 char buffer.
    else if(inputBuffer[0] == 's'){

      // MAX CHARS example with a 64 byte buffer:
      // s123456789a123456789b123456789c123456789d123456789e123456789f + CR + NL
      Serial.print("Letter 's' entered\tText entered = ");

      // Print out the chars in the buffer.
      for(int i = 1; i < strlen(inputBuffer); i++){
        Serial.print(inputBuffer[i]);
      }
      Serial.println();

      // Your code here that uses the char data after the letter "s" is entered.

    }
    memset(inputBuffer, 0, sizeof(inputBuffer));
  }
}


text:
How to switch 12V with esp32?
Hello i want to switch electric door lock (12V, 170mA) with esp32(3.3V). If is it possible I want use tranzistor. I tried to use IRF520, but it only worked with 5V. My sugestion is use 2 tranzistors one would switch 5V to IRF520 which would switch 12V. Can someone pro provide me some schematic, how to solve it? Thanks.

there are many tutorials and schematics on the internet ... there is no reason why you should be asking for someone to find them for you

If it works with 5V I guess, that the mentioned MOSFET goes into saturation for 5V, but not for 3.3V. You should buy a MOSFET, which has its saturation voltage at like 1V or so.

BC549 provides strong pull-down for IRFR5305, which is provides up to +12V at 16A with less than 0.09 Ohm channel resistance.
This circuit works well with ESP8266, I use it in some of my devices.
Don't forget about placing the flyback diode (EEV Blog, Wiki) in reverse polarity, parallel to the magnet. Place it as close as possible to the magnet!

How is the MOSFET gate going to be charged with Vcc? The transistor switches the path for ground. Isn't at least a pullup resistor at the MOSFET gate needed?

Oh, i really forget about that - I've added it on PCB but not in shema. I'll fix it now

Thank you very mutch.Of course I forgot the flyback diode  so I'll add it.

Nice answer! One tip: You could make the schematic a bit more “readable” by applying a few standard layout rules: 1) Put the (positive) supply voltage at the top 2) Put Ground (or negative supplies) at the bottom 3) Any input signals to the left and 4) Output signals to the right. You could look at the elaborate answer to this question.

@StarCat - Done :)

This works, but if you're swapping OP's FET, why not just spec a logic-level N-channel FET and decimate the BOM (no flyback, no BJT, no resistors) for the build?

Do you know a good N-channel MOSFET which can be fully opened from 3.3 volts?
In any case, OP needs the flyback diode if the magnet doesn't have one.

@gbg - When I connect the emitter to the ground rail, the ESP 01S locks up (I'm using GPIO2). Any ideas? I'm using the same components listed here, a 330 ohm resistor and a 2N4401. Thanks.

@user87507 Umm, this is strange. Please, show me some pictures of your device

A single, reasonably tough general purpose BJT is all you need here if you really want a simple solution.  The 2N4401 supports up to 600mA of current and has a 40V Vce max.  As long as the solenoid on the door lock has a snubber it doesn't need to be any more complicated than this unless you need isolation or have other constraints.
Note that below I've drawn a relay because it was easy, but you can just as well put your door lock's solenoid coil where the relay is drawn below (they're effectively the same type of device).

I have exactly this setup on an ESP8266 controlling a 24V relay and it works great.  I'm using an old 2N2222, which are long since obsolete, but the 2N4401 would do just the same.

Using a relay to control a door lock magnet is very bad idea because of this: https://youtu.be/XXW27KKHtc8?t=79 - Eve can take a strong magnet, apply it to a control device and boom! - door is just opened.

@gbg The "relay" here is standing in for the coil of the door lock, which OP says draws 170mA@12V.  The point is that you can switch any solenoid with just a BJT as long as it's not too big.

@gbg  As an aside, relays are used for door locks, especially big ones, but usually in installations where the relay is far from the door itself - in a control room cabinet deep in the building, etc.  If you can get access with a magnet to those relays, you're already well past the door that's locking you out.

If relay is in a secured compartment - no problem. But in same smart (not really) locks, the relay is located just outside, in a keypad or a fingerprint sensor box

@gbg True, but consumer grade IoT is not anything I'd put in charge of security in the first place, to be honest.

S in IoT is for Security :)


text:
platformio native unit test Arduino.h not found
I'm writing code for a microcontroller project using PlatformIO.
I have a couple of classes that I want to write unit tests for. I've not unit tested with pio before so I'm starting with one of the easier classes. I wrote out the start of my test:
#include "PixelRange.h"
#include <unity.h>

void test_forward_incrementation(void)
{
  PixelRange range = PixelRange(1, 5, 10);
  uint8_t currentIndex = range.getCurrentIndex();

  TEST_ASSERT_EQUAL(5, currentIndex);
}

int main(int argc, char **argv)
{
  UNITY_BEGIN();
  RUN_TEST(test_forward_incrementation);
  UNITY_END();
  return 0;
}

For my class:
#pragma once
#include <Arduino.h>

class PixelRange
{
public:
  PixelRange() {}
  PixelRange(int rows, int startingIndex, int endingIndex);

  void setReverseIteration(bool reverse);
  uint8_t getNextIndex();
  uint8_t getCurrentIndex();

  int getRowCount();
  int getStart();
  int getEnd();

private:
  bool _iterateInReverse = false;
  uint8_t _iteratorIndex = 0;
  int _rowCount;
  int _start;
  int _end;

  uint8_t forwardIteration();
  uint8_t reverseIteration();
};

And my platform.ini looks like this:
[env:adafruit_trinket_m0]
platform = atmelsam
board = adafruit_trinket_m0
framework = arduino
lib_deps = fastled/FastLED@^3.4.0

[env:native]
platform = native
test_ignore = test_embedded

I wanted to start by running the test in the native environment, but when I run it I get errors saying that I'm missing the Arduino.h file. Even odder, one of the errors is coming from a file that's not even under test.

I'm referring to the calculator example as far as setup and I don't see anywhere in the desktop test where Arduino.h is mocked.
Anyone have an idea of why this would be failing? Here's the full project in case that helps.

I suppose native means on the computer, not on the arduino, and the computer doesn't have a Arduino.h header. Why do you even need it? The uintX_t are defined in  header so if it's the only dependency, it should be all to just include it..


text:
Arduino UNO won't move servo
I have a simple MG996 servo motor and I am trying to make it move with my Arduino Uno. I tried different ways of wiring but nothing seems to work as fully expected.
For the wiring I followed this video: https://www.youtube.com/watch?v=b_xvu6wWafA and at 9:02 min the guy is showing how the wiring is done. As you can see in my photo, I have done the same thing (as you can see in the "my wiring" picture), with an external battery pack and everything but my code still does not work. No errors or anything, compiles and uploads perfectly. The code I was trying to execute is:
#include <Servo.h>

Servo myservo;

void setup() {
  myservo.attach(8);
}

void loop() {
  myservo.write(0);
  delay(1000);
  myservo.write(90);
  delay(1000);
}

This code is essentially trying to move the servo from 0 to 90 degrees back and forth. The pin is the correct one (#8). The arduino is receiving the right code (because I tried it with exemplary ones).
Important note: One thing I tried, however, was to not even have an external battery pack. Just connect the wires like so but instead of the 2 GNDs, only 1 GND and 1 +5V pin. That way I was able to move the servo only forward but never backwards! And every time I wanted to move it I had to write a higher degree value.
So the question is, is my wiring bad? I must be missing something.
Photos:

It looks like you have it wired to Vin? That's a voltage in pin. You probably want 5V.. It's pretty hard to tell anything from the pic, though; diagrams are easier to understand.

You have not connected the supply pin properly.
here is the connection diagram for the standard basic Arduino example
I also verified this on the video you have linked. Connect the 5V and you should be good to go.
https://wokwi.com/arduino/projects/306894988845777472


text:
ESP32 powered for atleast a year
How to power esp32 board this one with soil humidity sensor that sends data to server via wifi every 30 minutes for something around a year on battery? What battery type and capacity should I use for that? Or is there any better board you would recommend for this pourpouse? The setup will be indoors.

There's no generic answer, it depends on the actual circuit and its power consumption. If outdoors (and some indoor setups) I'd say solar + battery.

Your question is too broad without experimental, for example, have you done the measurement of your board when it is in operation, and when it is in sleep mode? Only when you have those values, you can then decided on whether it is a suitable board or not (e.g. does it cut off the USB chip when in sleep mode)? Choosing the battery depend on your form factor and application, as well as your circuit design. You can only decide that once you done the measurement an calculation.

Okay, let's do some calculations.
Assume that device sends data for 5 seconds (turn on, connect to the Wi-Fi, and so on) and drains (according to the docs) about 0.2A.
So, it works for 5 (secs) * 48 (turn-on's) / 60 minutes per day for 365 days.
So, it works for 5 * 48 / 3600 hours per day for 365 days.
So, it works about 24 hours per year.
0.2A for 24 hours is 4.8A for 1 hour.
Assume that efficiency of the power regulator is 80%
4.8  - 80 %
X    - 100%
X = 6 A*h
So, take three (to compensate self discharge and have some headroom) standard Li-Ion cells, or mid-size (about 8000 mAh) power bank, and you well be fine.
But you shall add some external clock (powered by own CR2032 cell), that will be turn power regulator and esp-device ON every 30 minutes.

I would use ESP-NOW instead of wifi. It can boot, read, and publish in well under 500ms instead of 5 seconds. On the 32, you could also probably craft a ULP routine that would only bother to fully wakeup+report if the moisture level changes.


text:
Arduino Hanging Not sure if software or hardware issue
I am trying to run a very simple program to glow LEDs in a certain fashion, I connected 9 LEDs to the GPIOs or digital pins, 2 To 10, via 220 Ohm resistors; when I am running the program it is hanging the Arduino after some time interval and LEDs stops glowing, not sure if it is a hardware issue or some bug in the software/code.
Here is the code:
int outGPIOsarr[9] = {2,3,4,5,6,7,8,9,10};

void setup() {

  for(int i=0; i<10; i++)
pinMode(outGPIOsarr[i], OUTPUT);
}

void loop() {

for(int i=0; i<10; i++)
 {
digitalWrite(outGPIOsarr[i],HIGH);
delay(10);
 }

for(int i=0; i<10; i++)
 {
digitalWrite(outGPIOsarr[i],LOW);
delay(10);
 }

}

Anything getting hot? Try using higher resistor values (470 or even 1k), you're drawing more than the allowed amps from a 328P (200mA IIRC)

@Mat , nothing is getting hotter , I checked it, one thing I observed is when I change the first argument of digitalwrite from outGPIOsarr[i] to respective pin number and change for loop from to run from 2 to 10 the code is running fine without a problem ! But I am not able to find good reasoning behind it !?

This is the UB!
The indexes in array in C++ counts from 0;
So, the last index in your array of 9 elements is 8.
All cycles must stop at 8. Yours are stops at 9.
Access beyond the existing element in the array is the Undefined Behavior - it hangs the MCU.

Oh well that was an embarrassing bug, thanks for pointing out >_<

and OP can't delete a question if it has an upvoted answer

But why this topic must be deleted?

because the question is not about the arduino, it is a general programming question, so it is off topic here ... any answers are also off topic here

I disagree. The reason is - OP doesn't know, what causes hanging - wrong firmware or wrong hardware.
So, to mark the question as off topic, you must literally answer the question.

https://arduino.meta.stackexchange.com/questions/2667/trivial-questions-must-be-off-topic

OP would like to remove the question because it is an "an embarrassing bug" and if not closed, with this count of votes it would be a "Hot network question" representing Arduino SE on the right side of every SE page.


text:
İs that possible to a function return String OR Int depends on address
Well, I'm trying to use a HMI display and this HMI storing datas in separeta addreses. Such as integers addr. is between 0x80000 to 0x9ffff and also for string's addr is between 0 to 0x1ffff.
At this point I want to make function which is return integer if addr is a integer addr OR it will return string if addr is String addr. is that possible to make two kind of return type for a method.
I will detect integer or string from addr value like this:
????    HMT_SendCMD_ReadVPN16(INT32U Addr)

if((Addr > 0x00080000) || (Addr < 0x0009FFFF))
    {
        return int (); // at here it call a fonction and it will return integer
    }

else if(Addr < 0x0001FFFF)
    {
         return String (); // at here it call a fonction and it will return String
    }

There are ways of doing it using objects, but it's really messy and convoluted and really not worth the effort. Simpler to just have two functions, one for each type.

Move your logic to a new function that works with either. Then define 2 different functions with the same name and different arguments as needed. they can be auto-magically called and C++ will detect which one you need. You then call your logic from inside each of the wrappers, so that you don't have to code the full logic twice.

is that possible to make two kind of return type for a method

No. Functions are declared with a single return type. What is the point anyway of returning a blank string?
You need to redesign.

What is the point anyway of returning a blank string? - well there would be normal fuction like String abc();  I have add symbolic . anyway, if god of arduino, says no, it's over. thanks a lot :)

If the task were to store something different at the given address,
or if you would want to return a String representation of the integer,
you might be able to do so, but Majenko's comment and Nick's response, suggesting a different approach, are better.


text:
Serial monitor constantly reads input with unknown characters
I am trying to read input from the serial monitor on my Arduino UNO using the new Arduino IDE 2.0 and send a specific infrared signal depending on the command.
I do this using the following code:
#include <Arduino.h>

/*
 * Define macros for input and output pin etc.
 */
#include "PinDefinitionsAndMore.h"
#include <IRremote.h>

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

    Serial.begin(115200);
    while(!Serial) ;

    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    /*
     * The IR library setup. That's all!
     */
    IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin

    Serial.print(F("Ready to send IR signals at pin "));
    Serial.println(IR_SEND_PIN);
    Serial.println("Commands: start, stop, links, rechts, heim, max");
}

/*
 * Set up the data to be sent.
 * For most protocols, the data is build up with a constant 8 (or 16 byte) address
 * and a variable 8 bit command.
 * There are exceptions like Sony and Denon, which have 5 bit address.
 */
uint16_t sAddress = 0x5540;
uint8_t sCommand_Start_Stop = 0x44;
uint8_t sCommand_Left = 0x44;
uint8_t sCommand_Right = 0x44;
uint8_t sCommand_Home = 0x44;
uint8_t sCommand_Max = 0x44;

uint8_t sRepeats = 1;

bool is_running = false;
String command;

void loop() {
  if(Serial.available()){
        command = Serial.readStringUntil('\n');

        Serial.print(F("Command received: "));
        Serial.println(command);

        if(command.equals("start")){
            sendIRCommand(sAddress, sCommand_Start_Stop);
            is_running = 1;
        } else if(command.equals("stop")){
            sendIRCommand(sAddress, sCommand_Start_Stop);
            is_running = 0;
        } else if(command.equals("links")){
            sendIRCommand(sAddress, sCommand_Left);
        } else if(command.equals("rechts")){
            sendIRCommand(sAddress, sCommand_Right);
        } else if(command.equals("heim")){
            sendIRCommand(sAddress, sCommand_Home);
        } else if(command.equals("max")){
            sendIRCommand(sAddress, sCommand_Max);
        } else{
            Serial.println("Invalid command!");
        }
    }
}

void sendIRCommand(int irAddress, int irCommand) {
  /*
     * Print current send values
     */
    Serial.println();
    Serial.print(F("Send now: address=0x"));
    Serial.print(irAddress, HEX);
    Serial.print(F(" command=0x"));
    Serial.print(irCommand, HEX);
    Serial.println();

    Serial.println(F("Send NEC with 16 bit address"));
    Serial.flush();

    IrSender.sendNEC(irAddress, irCommand, sRepeats);
}

In the process I encounter the problem that the serial monitor constantly reads unknown characters as alleged inputs, although I don't send anything. Because of the two unknown characters, even the proper commands can't be recognized correctly, which is a big problem. Here is the extract of the serial monitor:
15:53:42.987 -> START c:\PATH\TO\SCRIPT\command-sender.ino from Aug 16 2021
15:53:45.093 -> Using library version 3.1.1
15:53:45.094 -> Ready to send IR signals at pin 3
15:53:45.096 -> Commands: start, stop, links, rechts, heim, max
15:53:45.100 -> Command received: ��
15:53:47.107 -> Invalid command!
15:53:47.107 -> Command received: ��
15:53:49.122 -> Invalid comma��
15:53:49.122 -> Command received: ��
15:53:50.113 -> Invalid command!
15:53:50.117 -> Command received: ��
15:53:52.131 -> Invalid command!
15:53:52.131 -> Command received: ��
15:53:54.131 -> Invalid command!
15:53:54.131 -> Command received: ��
15:53:56.142 -> Invalid command!
15:53:56.142 -> Command received: ��
15:53:57.142 -> Invalid co+���Command received: ��
15:53:58.147 -> Invalid command!
15:53:58.147 -> Command received: ��start
15:53:58.932 -> Invalid command!
15:53:58.933 -> Command received: ��
15:54:00.950 -> Invalid command!

I checked the baudrate, use Serial.print and wait in the setup until the serial is initialized before I send data. I use 115200baud in the serial monitor in the IDE as well as New Line. All without success. How can I fix this problem?
Here is the URL for the PinDefinitionsAndMore.h if this is the root of the problem.
Update
When using VisualStudio Code with the PlatformIO extension, sending the commands works just fine. Here the unknown characters don't show up neither. It almost seems like the problem is related to the Arduino IDE 2.0 in some way.

did you wired something to pin 0 or 1?

@Juraj No, pin 0 + 1 are not used. There is also no physical connection of the two pins on the back of the board. Pin 2 + 3 are used for sensors

Can you please replace Serial.println(command); by Serial.println(command, HEX); and then post the serial output again. That should at least show us, what data is actually received.

@chrisl, Serial.println(command, HEX)???

did you try the not Beta version of Arduino IDE? version 1.8.15

Oops, that is really wrong. More like for(int i=0;i<command.length();i++){ Serial.print(command[i], HEX);} Serial.println(); Wanted to print each character as hex to also identify the non-printable characters.

@chrisl When using your code the output alsways results in FFFFFFF0FFFFFFF0

@Juraj I did not try the 1.* versions but PlatformIO in VSCode instead.

Mhh, then this seems to be a problem with what is send by the Arduino IDE 2.0 through serial (it should not send all high bytes with normal text). Since it is still beta, it might be a bug.

Check the baud rate and associated parameters (115200,N,8,1).


text:
Getting constant PWM value based on user input from serial monitor
I am trying to get a constant PWM value from the PWM pin based on the user input. For example: the user hits 1, the output PWM value is 100, if it is 2 the output would be 200. This will continue till the user enters a new number.
The issue I am having with my code is when I enter a number, the output of the PWM goes to that value for about a second and then goes back to 0. Can you please let me know what I am missing?
// Sketch: Blinking two LEDs by user
int test_pin=2; // declare pin10 as ledpin
int PWMvalue; // variable to store the number of blinks
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.println("What is the new speed?"); //Prompt User for Input
 while (Serial.available() == 0) {
    // Wait for User to Input Data
  }
  PWMvalue = Serial.parseInt(); //Read the data the user has input

  if (PWMvalue==0)
  {
    analogWrite(test_pin,0);
    }
    else if (PWMvalue==1)
    {
      analogWrite(test_pin,100);
      }
      else if (PWMvalue==2)
    {
      analogWrite(test_pin,200);
      }
      else if (PWMvalue==3)
    {
      analogWrite(test_pin,300);
      }
      else if (PWMvalue==4)
    {
      analogWrite(test_pin,400);
      }
      else if (PWMvalue==5)
    {
      analogWrite(test_pin,500);
      }
      else if (PWMvalue==6)
    {
      analogWrite(test_pin,600);
      }
      else if (PWMvalue==7)
    {
      analogWrite(test_pin,700);
      }
      else if (PWMvalue==8)
    {
      analogWrite(test_pin,800);
      }
      else if (PWMvalue==9)
    {
      analogWrite(test_pin,900);
      }
      else
    {
      analogWrite(test_pin,1023);
      }

  Serial.print("The user has choosen the number:");
  Serial.println(PWMvalue);
  Serial.println(" ");
}
```

I am using Arduino MKR NB 1500. I am using PWM pin 2

set Line ends to none in Serial Monitor.  line ending counts into available(). readInt waits one second for number, then it returns 0.

setting the line ends to none worked. Thanks Juraj!

why have you not included the serial console printout?

You wait for user input with a while (Serial.available() == 0), the you read the input with Serial.parseInt(). parseInt will wait a second for digits. It will end on a non digit character or timeout and return the number corresponding to received digits. If no digits were received a 0 is returned.
Serial Monitor has Line end setting. If there is some line ending selected, it will send line ending character(s).
Your waiting loop while (Serial.available() == 0) will end on line ending character which followed the number processed in previous loop. parseInt will not find a digit so it times out after a second and returns a 0, which causes setting the PWM to 0.


text:
Swap Serial pins of ESP8266?
I have designed and manufactured a PCB which contains an ESP8266 (ESP-WROOM-02D) chip with the serial uart pins connected to a 30pin connector. I made a mistake on the layout (first time designing a PCB), and have the RX (Pin 3) and TX (pin 1) pins connected incorrectly (swapped).
Is there a way to switch these pins in software? There's no nice way to physically modify and I was hoping to not have to have the boards manufactured again if I can avoid it.
Thanks!

no. there is not

You could potentially still fix this by using SoftwareSerial.
Instead of using the hard-wired serial, you can create one in software and use any pins you'd like... Have a look at this github project.
This work-around however requires you to have two unused pins to assign to SoftwareSerial.

the linked SoftwareSerial library is bundled with esp8266 Arduino boards support package

Can I reassign the two hardware serial pins to software serial? It is hardwired to pins 1 and 3...

@tommy-b-10, how do you flash the sketch into the esp?

@Juraj I flash the initial sketch before the esp is soldered to the board, then future flashes are done OTA using the esp wifi.

Had another crack at this and realised I needed to set the pinmode to function_3 for pins 1 and 3 before calling softwareserial.begin. Works perfectly now! Is there any downsides to using softwareserial? I have it working at 115200 baud but a little concerned about stability. Cheers!


text:
Parallel I/O - maybe use Machine code function call
I'm a newbie to arduino but been programming lots.
I have a project where I would like to output 4 bits to adjacent pins and read 4 bits from another (4) adjacent pins. (Imagine a matrix keyboard application).
To do it in C-C++ would take lots of instructions (and time) but machine code
OUTPUT:
OR (mask) -> output port      ; this clears bits target bits while leaving other bits as they were
AND (newdata) -> output port  ; this sets new data into target bits
INPUT:
port -> register
AND (register) (mask) -> register
Is there a way of implementing this as a call from IDE for instance.
I have come across many systems where multi language components can be compiled into one executable.
If it is not normally done, why not? Is it something that I should avoid for some reason?
Thanks
Dave

Looks at the PORT and PIN registers (assuming AVR). They can be manipulated directly from C or C++, no need for assembly.

If you have an AVR Arduino (like Uno, Nano, ...) this is a must read for this topic in the documentation.

What do you mean by "a call from IDE"? You might want to do some tutorials to learn the basics and technical terms. There are examples for matrix keyboards, I'm sure.

Thanks Mat and Chris. Excellent info.  Juraj, I'm using a 'clone' UNO but want the thing to work efficiently keep programme to minimum. Busybee, Sorry. I know IDE is not the correct term but wanted the question to be as elementary as possible.

If it's about manually triggered mechanical buttons, rather take care to be SLOW enough to get rid of bouncing effects. While waiting a few ms until a button settles, it does not matter how you read the button states.

You can manipulate the I/O ports directly from C++ without having to resort to assembly code.
The AVR micro in your Arduino (ATmega328P) has three ports (PORTB, PORTC and PORTD) with eight pins each (Px0, Px1, ... Px7). You control the ports using three 8-bit registers. Each bit in a register represents one physical pin (LSB is pin 0, MSB pin 7):

DDRx: data direction register. A bit set to "1" corresponds to output mode, "0" to input.
PORTx: data register. In output mode, "1" sets the port HIGH, "0" sets it LOW. In input mode, controls whether pull-ups are enabled ("1") or not ("0").
PINx: input and toggle register. Read it to get the status of all eight pins of the port at once. Writing to it toggles (LOW -> HIGH or HIGH -> LOW) the selected pins (e.g. PINC = 0b00100001; toggles pins PC0 and PC5).

With an Arduino, you don't have access to all the pins of all the ports. To get the mapping between Arduino pin names and ports, look at any good Arduino pinout reference (e.g. on the Arduino Uno page in the "Documentation" tab). You can see for example that all pins of port D are available as Arduino digital pins D0 to D7 on an Uno for example. The analog pins are from PORTC.

Macros are provided (by the AVR toolchain) for port and pin names to make things easier.
For example, PORTB is an alias for the PORTB register, you can assign to it as if it was a regular C++ variable. PB5 is the index of pin 5 in port B. So setting port B pin 5 to output without affecting the others can be written as:
DDRB |= (1 << PB5);

If you wanted to set the 4 lower pins of port D to output, and the 4 others to input, you could:
DDRD = 0b00001111; // or 0x0f

Here's an example of a minimal blink sketch:
void setup() {
  // Set PB5 (D13 - builtin led) LOW
  PORTB &= ~(1 << PB5);
  // Set PB5 mode to OUTPUT
  DDRB |= (1 << PB5);
}

void loop() {
  delay(1000);
  // toggle PB5
  PINB |= (1 << PB5);
}

The assembly generated is optimal, single instructions to set or clear a bit in I/O memory:
(See See compiled assembly output (Visual Micro) for how to get it)
// setup
  PORTB &= ~(1 << PB5);
 1f4:   2d 98           cbi     0x05, 5 ; 5
  DDRB |= (1 << PB5);
 1f6:   25 9a           sbi     0x04, 5 ; 4

// loop
  PINB |= (1 << PB5);
 246:   1d 9a           sbi     0x03, 5 ; 3

Another example, that blinks a led connected to A3 only when A2 is high:
void setup() {
  // Set PC2 and PC3 LOW (A2 and A3)
  PORTC &= ~((1 << PC2) | (1 << PC3));
  // Set PC2 to input, PC3 mode to output
  DDRC = (DDRC & ~(1 << PC2)) | (1 << PC3);
}

void loop() {
  delay(1000);
  // toggle PC3 only if PC2 is high
  if (PINC & (1 << PC2)) {
    PINC = (1 << PC3);
  }
}

Again, assembly generated is quite terse:
  if (PINC & (1 << PC2)) {
    PINC = (1 << PC3);
 202:   18 e0           ldi     r17, 0x08       ; 8
 252:   32 99           sbic    0x06, 2 ; 6
 254:   16 b9           out     0x06, r17       ; 6

(The SBIC instruction is fun: skip the next instruction if a bit in I/O memory is clear.)
You can even save the use of that register r17 by using PINC |= ... in this case:
  // toggle PC3 only if PC2 is high
  if (PINC & (1 << PC2)) {
    PINC |= (1 << PC3);
 250:   32 99           sbic    0x06, 2 ; 6
 252:   33 9a           sbi     0x06, 3 ; 6

Of course you can also resort to inline assembly, but that is an art in and of itself, and the syntax a bit peculiar. But for simple things, it is straightforward:
asm("sbi 0x03, 5;"); // toggle PB5

Some references:

ATmega328P Datasheet linked from here: Microchip ATMega328P page. See section 14 "I/O ports", and 36 "Register summary" for the I/O port addresses.
The AVR Instruction Set Manual (PDF) if you want to dive into that.
The AVR-GCC Inline Assembler Cookbook for details on using GCC's flavor of inline assembly for AVR


text:
ESP32 OTA update over MQTT using "update.h"
I am trying to do OTA over MQTT using update.h library. I am publishing firmware file over MQTT in a specified chunk size. The file is receiving at ESP32 end. I am supplying the received data to update.write. In start ~150 packet are written successfully. But after that update.write started to give error Wrong Magic Byte.
Here is the code snippet which I am using inside ESP32
#include "mqtt_handler.h"
StaticJsonDocument <256> root;
uint8_t temp[100] = {0};
size_t length ;
void otaHandler(byte *msg, unsigned int len)
{
deserializeJson(root,msg);
String command = root["command"];
if (command.equals("ota.start"))
{
    Serial.println("OTA.START via MQTT");
    if (!Update.begin(UPDATE_SIZE_UNKNOWN))
    {
        Update.printError(Serial);
    }
}
else if (command.equals("ota.write"))
{
    Serial.println("OTA.WRITE via MQTT");
    memset(temp, 0, 100);
    length = root["length"];
    String data = root["data"];
    for (int i = 0; i < length; i++)
    {
        temp[i] = data[i];
    }

    Serial.println(data);
    if (Update.write(temp, length) != length)
    {
        Update.printError(Serial);
    }
}
else if (command.equals("ota.end"))
{
    Serial.println("OTA.END via MQTT");
    if (Update.end(true))
    {
        Serial.printf("Update Success \nRebooting...\n");
    }
    else
    {
        Update.printError(Serial);
    }
}
else
{
    Serial.println("Something went worng");
}
}
void callback(char* topic, byte* message, unsigned int length) {
otaHandler(message,length);
}

In this code callback is the method which is called when an MQTT message arrived.This is the relevant code, if required I can share the complete code.
Message send by python application looks like as below:
{"command" : "ota.start"}
{"command": "ota.write", "length": length, "data": data})
{"command" : "ota.end"}

Below is the snapshot of data send by Python application in above ota.write message:

Below is the snapshot how my firmware file looks like:

I am sharing this snapshot to show the data format in which I am publishing firmware file.
Below is the snapshot of serial monitor:

Please suggest me if I am missing something on this.
Thanks

The message basically means that you have not formatted your image data correctly. The first byte must always be 0xE9 (as in your firmware picture). I suspect you are sending some ASCII representation of the data and not converting that back to binary as you should.

Looking at it more closely it looks like you're just blasting a decimal ASCII representation of the data that would be absolutely impossible to parse.

Yes I am sending in decimal ASCII like 0XE9 is 233. In which format does it expect data ?? Binary  ??

It expects binary data. It is your responsibility to turn your text representation back into the binary format it started as. I would suggest using HEX as your transport layer not decimal - and use zero padding. You can't tell if 3224465 is 32 244 65 or 3 224 46 5, for example. Keep it as hex, and always 2 characters per byte, then in your C code take each pair of hex characters and convert them back to binary.

You are just throwing an unparseable stream of ASCII decimal representations of the binary data at your code, then writing that ASCII data verbatim to the flash. That can never work.
Instead you need to pick an ASCII representation of your data that is actually parseable (I would suggest sticking to HEX representation and always 2 digits, so represent 0x6 as "06"), then when you receive a packet you must convert the content back into binary before sending it to the Update library.
As it is you take a byte (for example 0xE9) and convert that to ASCII decimal, which is 223. Then you write the 2, 2 and 3 as individual bytes to the flash as ASCII, resulting in 0x32,0x32,0x33 - or printing as decimal in an unparseable stream, 505051.