text:
AsyncWebServer giving wdt reset
I am using 3 Esp32 modules. One being master and other two being nodes.
Nodes are connecting to the master's AP. Master is connected with GSM module to execute the web api.
Master esp is having a Async Webserver which takes the http requests from the nodes and executes the appropriate web api. This web api returns the result and finally this result is sent back to the node as the response to the http request.
While running this code, Randomly on any request i face wdt reset.
Hence my question is, how should i handle the wdt resets and keep my program running softly.
E (32706) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (32706) task_wdt: - async_tcp (CPU 0/1)
E (32706) task_wdt: Tasks currently running:
E (32706) task_wdt: CPU 0: IDLE0
E (32706) task_wdt: CPU 1: async_tcp
E (32706) task_wdt: Aborting.
abort() was called at PC 0x400e1cc3 on core 0
Backtrace: 0x4008c434:0x3ffbe170 0x4008c665:0x3ffbe190 0x400e1cc3:0x3ffbe1b0 0x40084771:0x3ffbe1d0 0x4016aaf3:0x3ffbc0d0 0x400e307a:0x3ffbc0f0 0x4008a361:0x3ffbc110 0x40088b7d:0x3ffbc130

My Code Snippet is given below,
Master
HttpClient http(gsmClient, "www.mydummyserver.com", 80);
AsyncWebServer server(80);

const char* ssid = "ESP32-Access-Point";
const char* password = "123456789";
IPAddress ip(192,168,5,2);
IPAddress gateway(192,168,5,1);
IPAddress subnet(255,255,255,0);
const char* PARAM_MESSAGE = "message";

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

void setup() {

  Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  delay(100);
  WiFi.softAPConfig(ip, gateway, subnet);
  WiFi.softAP(ssid, password);

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

 server.on("/myApi", HTTP_POST, [] (AsyncWebServerRequest *request) {

        String message;
        if (request->hasParam(PARAM_MESSAGE)) {
            message = request->getParam(PARAM_MESSAGE)->value();
        } else {
            message = "No message sent";
        }

        http.setTimeout(20000);
        String postData = "Param1=abcd&Param2=pqrs";
        http.beginRequest();
        http.post("http://www.mydummyserver.com/testapi.php");
        http.sendHeader("Content-Type", "application/x-www-form-urlencoded");
        http.sendHeader("Content-Length", postData.length());
        http.beginBody();
        http.print(postData);
        http.endRequest();
        int statusCode = http.responseStatusCode();
        String response = http.responseBody();

        Serial.print("Status code: ");
        Serial.println(statusCode);
        Serial.print("Response: ");
        Serial.println(response);
        request->send(200, "text/plain", "Response: " + message);

    });

 server.onNotFound(notFound);

    server.begin();

}

void loop() {

}

Node
HTTPClient httpClient;

void setup() {

  Serial.begin(115200);

  WiFi.begin("ESP32-Access-Point", "123456789");

  Serial.print("WiFi ");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(10);

  }

  Serial.println("connected:" + WiFi.SSID());

}

void executeApi() {

  Serial.println("Executing Api...");

  httpClient.setTimeout(20000);
  httpClient.begin("http://192.168.5.2/myApi");
  httpClient.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  String contentStr = "Param1=abcd&Param2=pqrs";

  int httpResponseCode = httpClient.POST(contentStr);

  Serial.print("HTTP Response code: ");
  Serial.println(httpResponseCode);

  httpClient.end();

}

String cmd = "";
void loop() {

  if (Serial.available() > 0) {

    cmd = (Serial.readStringUntil('\n'));

    if (cmd.length() > 0) {

      if (cmd == "api") {
        executeApi();

      }

    }

  }

}

For sulutions i have tried following things,
a. I tried to write this into the loop() function.
 while(true){
   delay(1);
 }

b. Tried disabling the wdt
disableCore0WDT()
disableCore1WDT()

but none of these giving good results.

How do you wire the GSM module with the master, I don't see any code in your master related to configure or setup for communicating with the GSM. Is there any reason your node url endpoint is testapi, while it does not exist on your master's route (your master has a route handler for endpoint myApi. is your node connecting to web server directly instead of the master (which is a relay/proxy server).

@hcheung Hi, Due to privacy issues i could not share the real data.
GSM module and ESP are connected using HardwareSerial. I have corrected the code mistake for url endpoints. My node is connecting to master first and then it is executing remote server apis.

The following recommendations, as you aren't providing enough relevant info:

Install ESP-exception decoder and analyse your backtrace - Post it here so we can see in detail what caused the wdt
AsyncWebServer tends to cause this behavior if a response takes too long; a well placed yield() sometimes helps to prevent this behavior - to analyse you need ESP-exeption decoder
As loop() is running on core1 some/no process (idle) on core0 can cause the behavior. You can look up "task assignment to cores" on how to manually distribute the tasks (or send a yield() timed to core0 to reset the wdt)
Placing time-outs in combination with sleep/deep sleep (although you don't seem to use them) are also causes for wdt resets
A hackey trick is to set CONFIG_ASYNC_TCP_USE_WDT 0, but it is OK for testing

If you look into async_tcp for the possible culprit you see one line xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
Here is an example of how I use it to prevent wdt resets. Place in setup():
disableCore0WDT();
disableCore1WDT();
disableLoopWDT(); // You forgot this one !

and because of this routine in the async_tcp lib:
static void _async_service_task(void *pvParameters) {
  lwip_event_packet_t * packet = NULL;
  for (;;) {
    if (_get_async_event(&packet)) {
      #if CONFIG_ASYNC_TCP_USE_WDT
      if (esp_task_wdt_add(NULL) != ESP_OK) {
        log_e("Failed to add async task to WDT");
      }
      #endif
      _handle_async_event(packet);
      #if CONFIG_ASYNC_TCP_USE_WDT
      if (esp_task_wdt_delete(NULL) != ESP_OK) {
        log_e("Failed to remove loop task from WDT");
      }
      #endif
    }
  }
  vTaskDelete(NULL);
  _async_service_task_handle = NULL;
}

I set the `CONFIG_ASYNC_TCP_USE_WDT 0` and it works so far.

Hi .. thanks for the detailed suggestion. i tried this too but still the same error happening, Can u guide me more ?

also when i paste the following error i have mentioned in questions does in exception decoder it prints nothing.. I guess the exception clearly states the issue without any traces.

You have to paste the part starting after Backtrace: ==>0x4 to the end into thedecoderits not possible to hve nothing, So the sequence is compile and upload, serial moiitor wait till error copy & paste backtrace ESP decoder -> copy result THAN post to your question (edit!) Thanks

Hi . I have pasted in question what my serial monitor is showing. Other than this no other error data serial monitor is showing.

IF YOU WANT HELP I need what I posted above you have to do it in your environment as I can not decode the backtrace without your elf file and all your settings/libs/path/version etc - please help me to help you

Short answer
increase the size of the _async_queue in AsyncTCP.cpp
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));

from 32 to 64 or even higher if you can spare the space
Detailed (but possibly incorrect) explanation:
After looking at the OS calls, I found that in AsyncTCP.cpp
The event queue is created as:
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));

Later the items are added with a Timeout of portMAX_DELAY, for example:
static inline bool _send_async_event(lwip_event_packet_t ** e){
    return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS;
}

Since (at least when using the AsyncWebserver), both the queueing and the dequeuing are done on the same task (async_tcp), as soon as there are 32 events in the queue the moment the next event is to be added, the task will block indefinitely, causing the TWDT to be triggered.
So the solution might be to have the event queueing/dequeueing done in different tasks (maybe intended, since it already is an os queue) or increase the queue size to a value that will not be reached. Since the queue items are not that large, I just increased it to 256 to be on the safe side.
I am not sure if this explanation is correct, since I can't find the code where async_tcp feeds or kicks the watchdog during normal operation. So if someone knows how it works and could tell me, it would be greatly appreciated.

Thanks PiffPoff, increasing the queue size to 256 in AsyncTCP.cpp helped a lot getting rid of error below :

E (705728) task_wdt: Task watchdog got triggered. The following tasks
did not reset the watchdog in time: E (705728) task_wdt: - async_tcp
(CPU 0/1) AsyncTCP.cpp
_async_queue = xQueueCreate(256, sizeof(lwip_event_packet_t *)); Configuration
ESP32-S3 8Mb PSRAM 16Mb Flash
Arduino IDE
arduino-esp32 core 2.0.8
Wifi mode : Access Point


text:
D1 Mini + TFT & I2C Connector Shield not going into deepSleep
I'm trying to write a sketch to use a Wemos D1 mini connected to several shields including a LOLIN TFT & I2C Connector Shield (v1.1.0). This powers a small ePaper display (LOLIN 2.13" diagonal ePaper/eInk display) with a TFT e-Paper Cable.
The problem I'm running into is that I can't get the board to either boot properly or get out of deepSleep due to the pin assignment of the TFT display.
I have placed the following code before the void setup() as described in the manufacturer's GitHub example for the board:
/*D1 Mini*/
#define EPD_CS D0
#define EPD_DC D8
#define EPD_RST -1  // can set to -1 and share with microcontroller Reset!
#define EPD_BUSY -1 // can set to -1 to not use a pin (will wait a fixed delay)

By doing this, however, it results in the board entering a boot loop when I try to connect D0 --> RST
If I leave the D0 --> RST disconnected, the board will successfully run the sketch and enter into deepSleep but will not be able to Wake Up after a predetermined amount of time (10seconds).
I see the Builtin LED flash after 10seconds and there is some activity on the serial monitor so I suspect that the board is trying to wake up however it is unable to with the D0 disconnected to the reset pin.
If I try to connect the D0 --> RST after the board has gone to deepSleep and before the timer ends, it continues to sleep until the 10 seconds is completed, then starts its boot loop again with the Built-In LED flashing constantly.
Has anyone else had success in this?  I suspect I'm missing something very simple but cannot find much info on this shield anywhere.

you can use any pin as CS, it doesn't need to be D0. some pins on esp8266 have constraints https://electronics.stackexchange.com/questions/402066/esp8266-free-gpios-for-relay-switching/404845#404845

Thanks for your reply, Juraj.  I have the sketch successfully running now using your suggestion and remapping the CS to another pin.  However, unless I'm doing it incorrectly, this means I have to connect each pin individually between the D1 mini and the display using jumper cables without being able to use the TFT e-Paper Cable.  So now I am wondering if it is possible to remap the pin outputs so I can still use the ePaper cable with one connection between the board and display?

I would remove the CS wire from the connector on the shield  end and extend it with with a jumper wire

source: Stack Exchange

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

sort: votes


text:
How to pause the analog value according to input signal applied to a particular digital pin?
I'm working with a digital blood pressure meter using arduino nano. I need to display the pressure reading during inflation and deflation of the cuff instantly. And when an input signal applied to a particular pin during deflation, I need to print the pressure value at that time of input signal, to a display. How to code for this logic. I made the code for showing pressure value during inflation and deflation. But need to pause the value and display constantly the pressure value at the time of input applied to the arduino pin. How this pausing of value can be done?.
Finally I need to print both the systolic and diastolic pressure value constantly as: 120/80 mmHg (systolic/diastolic mmHg)
In this project, the systolic pressure is noted when there is an input at digital pin.
In the case of diastolic pressure, it is noted according to input pulse duration. That is, If the duration of pulse is greater than 50 milli-seconds, print the diastolic pressure as current pressure minus the pressure when pulse duration equal to 50 milli-seconds.
Below is the code I have written for printing the systolic and diastolic pressure instantly.
#include <LiquidCrystal.h>//Don't forget to enter this library

LiquidCrystal lcd(12, 11,  10, 9, 8, 7);

int analogInPin = A1;     // Analog input pin that the pressure sensor output is attached to

int pressure = 0;
int sensorValue = 0;        // value read from the pressure sensor via the amplifier stage

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

void loop() {
lcd.clear();
sensorValue = analogRead(analogInPin);

pressure = sensorValue*(0.9226)-267.7; //Pressure value according to sensor value
  lcd.setCursor(0,1);
  lcd.print("mmHg: ");
  lcd.print(pressure);
  delay(100);

}

I'm using a different method to note systolic as well as diastolic pressure values, like the stethoscope doing the job in conventional measurement method. The dual microphone arrangement will capture the sounds( korotkoff ) of blood flow. This sounds are processed (independent to arduino) by the external analog circuitry which outputs a 5VDC at every noticeable instant of pulse(during blood flow). This signal is then fed to a digital pin of arduino. Here, when the 5V signal reaches at the digial pin first, we note the systolic pressure as the pressure at the instant when the 5V signal is generated first. In the case of diastolic pressure, the generated 5V signal from the circuit is compared with an externally given unit step 5V using comparator. This compared signal output is fed to another digital pin of arduino, where the diastolic pressure is noted according to the input 5V pulse signal duration( Eg: If the duration is greater than  50ms ), the diastolic pressure is the pressure at which the pulse duration which is equal to 50ms).
I'm totally frustrated with remaining parts of code as mentioned.
Thank you in Advance..!!

the answer to your question is in your own code, right after delay(5000);

I need to print the two pressure values as Systolic/Diastolic with respect to the input signal to particular digital pins. And these values should displayed constantly as it is the final measurement value. Like: "Your Blood Pressure is: 120/80 mmHg"

The Systolic/Diastolic pressure is the two pressure levels noted at instant when the signals are reached by externally to any two digital pins at two different time

so, what is giving you the problem? .... you already have code for displaying data depending on pin input

your code is poorly formatted ... that makes it more difficult to see program flow and more difficult to determine where to insert additional code for expanded functionality

I just optimized the code for better understanding (I hope). Yes, I already have code for displaying data depending on pin input. That's working nice. But, I need to print the two pressure values among these broad pressure values, depending on an external signal  as input to a digital pin. This is what I need to print constantly as Systolic pressure during the measuring of pressure.

ok, now i know that i do not understand what you are trying to do ... my apologies ... maybe someone else can understand what you are asking

In my project, The pressure is given to the sensor externally and it is represented as inflation here and after a pressure value of (say: 180 mmHg), the deflation valve is activated to decrease the pressure inside the cuff gradually. at this time of deflation, at a particular time of deflation, an input from external microphone is reached at a digital pin (say: pin4). Here, I need to pause or print the pressure value at the time of input signal given.

Can I hope someone will solve my problem?. Anyway, thanks for follow up @jsotola

i think that the problem may be with your thinking that the displaying of data is somehow related to acquiring data .... the two functions are totally separate .... what you do with data, is totally irrelevant to the "read data function" ... how you obtained the data is totally irrelevant to the "display data function"

What is your overall hardware setup? Do you have the pulse detection circuit connect to the Arduino? My understanding of systolic pressure change is caused by the oscillation and therefore it can't just detected by reading the pressure. The amplitude of the pulse change when the pressure changed. The maximum amplitude represents the mean arterial pressure, and both systolic and diastolic can then be calculated based on the obtained mean arterial pressure. To obtain the pulse amplitude, you need a sensor (e.g. microphone) and a high-pass filter to filter out the pulse and the amplitude.

Sir, I'm using a different method to note both the systolic as well as diastolic pressure. I just added the description of my hardware part in above main question. Please find it at the bottom of my code part.

Still your code has nothing about the digital signal you mentioned. You need to read the change of the signal and record the pressure as diastolic. If you are using the cuffless technique, I would suggest you read the pulsein()   function that might be useful for your application.

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


text:
MAX7219 with 8digit 7seg array
I have a concern about the library port handling. I have used direct port direction manipulation successfully in previous projects but there seems to be a problem here.

// This code mostly taken from the example
#include "LedControl.h"

LedControl lc=LedControl(11,13,10,1);
//LedControl lc=LedControl(12,11,10,1); // original
// pin 12 is connected to the DIN pin (now MOSI 11)
// pin 11 is connected to the CLK pin (now SCK 13)
// pin 10 is connected to the CS pin  (now SS 10)
// 1 as we are only using 1 MAX7219

// I am actually using all arduino pins except 12 for my project
#define PD_MSK  B11111100 // Data pins PD2..7 (pins2..7)
#define PB_MSK  B00000011 // Data pins PB0,1 (pins8,9)
#define PC_MSK  B00001111 // Data pins PC0..3 (pins 14..17)

void setup()
{
// set pins 2..9 as inputs
  DDRD = DDRD & !PD_MSK; // this works OK
  DDRB = DDRB & !PB_MSK; // configure ports D,B inputs *** doesnt work with this
 // pinMode(8, INPUT); //*** does work with this
  //pinMode(9, INPUT); //*** does work with this

  DDRC = DDRC | PC_MSK; // configure PortC0..3 as outputs
  PORTC |= 0x0F; // set PortC0..3 high (default)

  // the zero refers to the MAX7219 number, it is zero for 1 chip
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen

}
void loop()
{
  //numbers 7 to 0
  for (int a=0; a<8; a++)
  {
    lc.setDigit(0,a,a,false);
  }

  delay(1000);

  //display number 8 on all segments
  for (int a=0; a<8; a++)
  {
    lc.setDigit(0,a,8,false);
  }
  delay(1000);

  // numbers 7 to 0 reverse order
  for (int a=8; a>=0; a--)
  {
    lc.setDigit(0,a,a,false);
    //delay(100);
  }
  delay(1000);

}

The direct port direction setting does not seem to allow the library to work while the pinMode commands doing the same job do. I note that the library uses software SPI but I would like to use hardware if possible. I have certainly used hardware SPI with frequent port direction changes on the remaining pins for other projects.
Any insight as to why this problem occurs?
Thanks.

What is the connection between "the library does not work if I setup ports manually" and "I would like to use hardware SPI"?

Since most libraries come as Open Source, did you peek into its sources? Is this one open? If so, what did your research reveal?

The ! is a logic operator. Bitwise variant is ~

However after the start/restart DDRx are cleared and configured as inputs, so I don't see any point in those &=

What tells "LedControl.h" that you are using hardware SPI vs software SPI?

As always I recommend the old RTFM (read the f***ing manual) of the LedControl.h library.
In the FAQ its clearly stated:

Why don't you use the hardware SPI-Bus of the Arduino?
When I wrote the first version of the library I didn't knew much about
  the Arduino or AVR processors in general and I knew nothing about
  writing code for the hardware SPI-bus on an ATMega. But I knew how the
  SPI protocol works and how I could make this work using simple
  digitalWrite() commands. I turned out the library code is fast enough
  for common use cases, so there is no need for doing Hi-Speed
  communications.
Other strong points in favour of the (admittedly trivial) code design
  are - Use any three free IO-Pins of your board for the hardware -
  Simple to debug. Much easier than managing 3 differnt SPI devices
  connected to the same hardware bus - Library is easily portable to
  other platforms, since it uses only two very basic functions from the
  Arduino language

So with this library you clearly have never used hardware SPI (although you could use the pins, but only via softwareSPI)

Answer #2 pointed out that I had used the wrong operator to set the port direction. (! instead of ~ - bitwise.) My mistake! I want to use hardware SPI in my eventual project (this was just a test) as it can be faster. I used this library to ensure that the external hardware worked -it does now. Using different pins has no benefit in my case so I will probably write my own (hardware) SPI driver. I already have a port direction control system to create a 8bit IO bus for use with other external hardware - if I copy it correctly this time. Thanks to all who took time and found my error.


text:
Arduino /dev/ttyUSB0 permission denied even when user added to group "dialout' on Ubuntu 18.04
I bought Arduino Mega board (CH341 usb) and I am able to connect to /dev/ttyUSB0 (upload to device) only by using sudo.
OS: Ubuntu 18.04
What I've tried:

I have downloaded Arduino IDE and added my user to dialout group. Logged out and logged in. Still nothing.
Installed Arduino by using apt
Installed Arduino by using snap

For all three cases it worked only by running as root (sudo actually). I saw couple of answers for Ubuntu 14.04 but none of answers didn't help.
I guess some other device access permissions are missing but I still didn't find any solution.

After some struggle I figured out that I need to add my user to "tty" group as well.
There's another approach that involves udev rules modification for certain vendor:device and update of device's ownership but this seems more sane approach.
To recap:

Add your standard user to the group "dialout'
sudo usermod -a -G dialout your-username

Add your standard user to the group "tty"
sudo usermod -a -G tty your-username

Logout/Login

Hope this helps

Sometimes a restart may be required. Logging Out / In may not be enough.


text:
Issues controlling a 10,1 capacitive panel with Arduino
Some days ago I had the inestimable help of hcheung in this forum to help me find some libraries on github to control a capacitive panel with a HT5xx6 controller. The libraries and code are here.
I have copied and created the libraries into a.h and .cpp files and placed where arduino IDE can find them and run the sketch. The startup works fine, meaning the panel is initialized.
However it doesn't give reliable data. Any time you touch the panel in a specific location it does not give a single set of coordinates, it sometimes give 2 or 3 set of coordinates and most of the time 15. This is as if the panel would detect 15 touches!
Even more issues: the coordinates are never the same in one fixed location. So the data is not reliable and I don't know what I am doing wrong.
Has anybody gone through this experience before?
Thanks for your help in advance!
Take care.
Joan.

is your panel the capacitive type for certain?

Hi jsotola, yes it is. I have the TDS and it is clear. https://focuslcds.com/content/FT5X26.pdf. Thanks.

The ISR might be fired up multiple times during the touch. Can you try to switch to another library https://github.com/sumotoy/FT5206? This one allows you to set your own interrupt pin and disable the interrupt when the touch is detected, read the coordinates and check against old coordinates. Read the example codes provided.  For random coordinates issue, make sure your power supply can provide sufficient power (1A-2A), and you might want to add a 10uF capacity between Vcc and GND.

Hello, thanks for the comment. I have tried all the above indications and still have the same issue. I have uploaded 3 videos on youtube so you can see what is happening, maybe this helps:

Part 1 Video [https://youtu.be/UwGcfkD-O-Q] - Part 2 Video [https://youtu.be/80RHSga8HTM] - Part 3 Video [https://youtu.be/yidqZx6y918]


text:
Debugging different serial receive / send behavior between Uno & Mega
I have a simple text parser (as a component of a larger project) coded up and seemingly working correctly. It parses a key-value delimited command like the following: <key1=value1;key2=value2;key3=value3>.
At present, the functionality is very silly just to test it out: when the Arduino finds a key named "text", it composes a response of a similar form, but just with one key "text_return" and the same value, and sends it back via serial. That is, when the command <key1=value1;text=123;key3=value3> is sent, I expect a response from the Arduino of <text_return=123>.
I then am connecting the board to my laptop via USB, and testing it out, both with the Serial Monitor in Arduino's IDE, and with a simple program coded in python.
So here's the confusing part:

Serial Monitor with Uno: works
Python with Uno: works
Serial Monitor with Mega: works
Python with Mega: does NOT work

Specifically, by "does not work", I mean that the Mega seems to receive the serial input from the program, but does not issue a response.
Here's the terminal output from test #2 as displayed by the python program, showing the command-response I'd expect (I parsed the received command into a dict):
SENT: <text=1953>
SENT: <text=1954>
SENT: <text=1954>
SENT: <text=1954>
SENT: <text=1954>
SENT: <text=1954>
SENT: <text=1954>
SENT: <text=1954>
RECD: {'text_return': 1954}
SENT: <text=1954>
RECD: {'text_return': 1954}
SENT: <text=1954>
RECD: {'text_return': 1954}
SENT: <text=1954>
RECD: {'text_return': 1954}

And here's the terminal output from the non-working test#4 - i.e.: no response.
SENT: <text=2001>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2002>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>
SENT: <text=2003>

In all cases, I'm using 9600 Baud; the only change between the two tests is that I select the Uno vs. Mega / Mega 2560 board in the Arduino IDE.
The Mega board is an Elegoo Mega2560 R3. The code may be extraneous, but to help:
Opening the port to the arduino from python
def FindArduino(baud=9600, timeout=0):
  initial_time = time.time()
  arduino_found = False
  attempted = False
  while not attempted or time.time() - initial_time < timeout and not arduino_found:
    attempted = True
    ports = serial.tools.list_ports.comports(include_links=False)
    for port in ports:
      manufacturer = port.manufacturer
      if manufacturer and 'arduino' in manufacturer.lower():
        arduino_port = port
        arduino_found = True

  if arduino_found:
    try:
      arduino = serial.Serial(arduino_port.device, baud, timeout=0)
      arduino.reset_input_buffer()
      arduino.reset_output_buffer()
    except serial.SerialException:
      arduino_found = False

  if arduino_found:
    return arduino
  else:
    return None

Sending the serial in python, to Arduino
  cmd = '<text=%d>' % (time.time() - 1586218411)
  print('SENT: %s' %cmd)
  cmd = bytes(cmd, 'ascii')
  arduino.write(cmd)
  time.sleep(.1)

Receiving the serial in python, from Arduino
  cmds = []

  if (arduino.in_waiting>0):
    buffer += arduino.read(arduino.in_waiting).decode('ascii')
    while COMMAND_END_CHAR in buffer:
      end_char_pos = buffer.find(COMMAND_END_CHAR)
      potential_command = buffer[:end_char_pos]
      if COMMAND_START_CHAR in potential_command:
        cmds.append(potential_command[potential_command.find(COMMAND_START_CHAR)+1:])
      buffer = buffer[end_char_pos+1:]

  return (buffer, cmds)

And the full code on the Arduino itself
// command indicators
char START_MARKER = '<';
char END_MARKER = '>';

const int MAX_KEY_VALUE_PAIRS = 3;  // maximum number of key-value pairs in message
const int MAX_ELEMENT_CHARS = 30;  // the maximum number of characters (+1 for terminator) in a key or a value

// message format: <key1=value1;key2=value2;key3=value3>
const int MAX_MESSAGE_CHARS = (MAX_KEY_VALUE_PAIRS * (MAX_ELEMENT_CHARS + 1)) * 2 + (MAX_KEY_VALUE_PAIRS - 1) + 2;  // maximum message size

char received_chars[MAX_MESSAGE_CHARS];
bool new_data = false;
char written_chars[MAX_MESSAGE_CHARS];

char *text =  {'\0'};

void ParseData(char *str) {
  // This picks off the ;-delimited key-value pairs and assigns them to a multi-dim array
  char * pch;
  int pairs_count = 0;
  char config[MAX_KEY_VALUE_PAIRS][2][MAX_ELEMENT_CHARS];

  pch = strtok(str, "=");

  while (pch != NULL)
  {
    strcpy(config[pairs_count][0], pch);
    pch = strtok(NULL, ";");
    if (pch == NULL) break;

    strcpy(config[pairs_count][1], pch);
    pairs_count++;
    pch = strtok(NULL, "=");
    if (pch == NULL) break;
  }

  for(int i=0;i<pairs_count;i++) {
    if (strcmp(config[i][0], "text")==0)
      strcpy(text, config[i][1]);
    WriteSerial();
  }
}

void ReadSerial(){
  // After calling ReceiveText to empty the buffer, if a complete command has been found,
  // parse that command.
  new_data = ReceiveText();
  if (new_data == true) {
    char temp_chars[MAX_MESSAGE_CHARS];  // temporary array for use when parsing
    strcpy(temp_chars, received_chars);
    received_chars[0] = '\0';
    ParseData(temp_chars);
  }
}

void WriteSerial(){
  sprintf(written_chars, "<text_return=%s>\n", text);
  Serial.write(written_chars);
  written_chars[0] = '\0';
}

boolean ReceiveText() {
  // This dumps the characters on the buffer so far received_chars, searching for an END_MARKER
  // along the way; if it finds one, it goes back to find a START_MARKER; if that is also found,
  // the string within is the ;-delimited set of key value pairs
  static boolean recv_in_progress = false;
  static byte ndx = 0;
  char rc;

  boolean new_data = false;
  while (Serial.available() > 0 && new_data == false) {
    rc = Serial.read();

    if (recv_in_progress == true) {
      if (rc != END_MARKER) {
        received_chars[ndx] = rc;
        ndx++;
        if (ndx >= MAX_MESSAGE_CHARS) {
          ndx = MAX_MESSAGE_CHARS - 1;
        }
      } else {
        received_chars[ndx] = '\0'; // terminate the string
        recv_in_progress = false;
        ndx = 0;
        new_data = true;
      }
    } else if (rc == START_MARKER) {
        recv_in_progress = true;
    }
  }
  return new_data;
}

void setup() {
  Serial.begin(9600);
  text = (char*)malloc(25);

  received_chars[0] = '\0';

}

void loop() {
  ReadSerial();
}

UPDATE
Using the suggested libraries, I updated the code. The comms in both directions for simple test data are working, though I can't seem to convert the packet received by the Arduino into a string correctly.  Here is the output I see from my python terminal; I'd expect to receive back the first character of what was sent (i.e.: the "0", then "1"), rather than just the initialized value of "S".
SENT: 0.20
RCVD: S
SENT: 0.41
RCVD: S
SENT: 0.61
RCVD: S
SENT: 0.82
RCVD: S
SENT: 1.02
RCVD: S
SENT: 1.23
RCVD: S
SENT: 1.43
RCVD: S
SENT: 1.64
RCVD: S

Python code
import time
from pySerialTransfer import pySerialTransfer as txfer

if __name__ == '__main__':
  try:
    link = txfer.SerialTransfer('/dev/cu.usbmodem14201')

    link.open()
    time.sleep(2) # allow some time for the Arduino to completely reset
    base = time.time()

    while True:
      time.sleep(0.2)
      s = '%.2f' % (time.time() - base)
      l = len(s)
      for i in range(l):
        link.txBuff[i] = s[i]

      link.send(l)

      while not link.available():
        if link.status < 0:
          print('ERROR: {}'.format(link.status))

      response = ''
      for index in range(link.bytesRead):
        response += chr(link.rxBuff[index])

      print('SENT: %s' % s)
      print('RCVD: %s' % response)

  except KeyboardInterrupt:
    link.close()

Arduino code
#include "SerialTransfer.h"

char str[100];

SerialTransfer myTransfer;
int LED = 13;

void blinkLED(int n)
{
  for (int i = 0; i < n; i++) {
    digitalWrite(LED, HIGH);
    delay(150);
    digitalWrite(LED, LOW);
    delay(150);
  }
}

void setup()
{
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  str[0] = 'S';
  str[1] = '\n';
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  blinkLED(2);
  delay(500);

  // send bytes
  myTransfer.txBuff[0] = str[0];
  myTransfer.sendData(1);
  if(myTransfer.available())
  {
    blinkLED(60);

    // receive bytes
    byte bytes_to_read = myTransfer.bytesRead;
    for(byte i = 0; i < bytes_to_read; i++)
      strncpy(str + i, myTransfer.rxBuff[i], 1);

  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

Thank you!

start debugging by replacing ReadSerial(); in loop() with WriteSerial() to send pre-determined data .... include a 5 second pause

Good suggestion - just tried that delay(1000); WriteSerial(); in the loop. Beginning to pinpoint - I'm not throttling my python (as I'm simulating the data pipeline at present, going much faster than it will with real data). So my test message gets sent to Mega ~20x per second. Perhaps that's keeping it from replying, or overwriting memory where it would reply? When I throttle the python code to once every 1s, the problem disappears. Throttling wasn't necessary for the Uno. I'lll experiment to find level of throttling necessary, but any thoughts as to why throttling needed, or diff from Uno?

It would be easier if you used Arduino <--> Python compatible libraries to ensure the communication between the two is robust and reliable. An example of such libraries would be pySerialTransfer and SerialTransfer.h.
pySerialTransfer is pip-installable and cross-platform compatible. SerialTransfer.h runs on the Arduino platform and can be installed through the Arduino IDE's Libraries Manager.
Both of these libraries have highly efficient and robust packetizing/parsing algorithms with easy to use APIs.
Example Python Script:
from time import sleep
from pySerialTransfer import pySerialTransfer as txfer

if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM17')

        link.open()
        sleep(2) # allow some time for the Arduino to completely reset

        while True:
            link.txBuff[0] = 'h'
            link.txBuff[1] = 'i'
            link.txBuff[2] = '\n'

            link.send(3)

            while not link.available():
                if link.status < 0:
                    print('ERROR: {}'.format(link.status))

            print('Response received:')

            response = ''
            for index in range(link.bytesRead):
                response += chr(link.rxBuff[index])

            print(response)

    except KeyboardInterrupt:
        link.close()

Example Arduino Sketch:
#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  myTransfer.txBuff[0] = 'h';
  myTransfer.txBuff[1] = 'i';
  myTransfer.txBuff[2] = '\n';

  myTransfer.sendData(3);
  delay(100);

  if(myTransfer.available())
  {
    //do stuff with received packet data
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

Note that you can send more than just individual chars with these libraries. It is possible to transfer floats, ints, bytes, arrays, and even structs (or any combination of the like) within your program using the libraries! See the examples in SerialTransfer.h for more info
For theory behind robust serial communication, check out the tutorials Serial Input Basics and Serial Input Advanced.
EDIT:

Applying the above example to your case, you can use the following code:
Python:
import time
import struct
from pySerialTransfer import pySerialTransfer as txfer

def stuff_float(txfer_obj, val, start_pos=0):
    '''
    Description:
    ------------
    Insert a 32-bit floating point value into the (pySerialtxfer) TX
    buffer starting at the specified index

    :param txfer_obj: txfer - Transfer class instance to communicate over serial
    :param val:       float - value to be inserted into TX buffer
    :param start_pos: int   - index of TX buffer where the first byte of
                              the float is to be stored in

    :return start_pos: int - index of the last byte of the float in the TX
                             buffer + 1
    '''

    val_bytes = struct.pack('f', val)

    txfer_obj.txBuff[start_pos] = val_bytes[0]
    start_pos += 1
    txfer_obj.txBuff[start_pos] = val_bytes[1]
    start_pos += 1
    txfer_obj.txBuff[start_pos] = val_bytes[2]
    start_pos += 1
    txfer_obj.txBuff[start_pos] = val_bytes[3]
    start_pos += 1

    return start_pos

if __name__ == '__main__':
  try:
    link = txfer.SerialTransfer('COM17')

    link.open()
    time.sleep(2) # allow some time for the Arduino to completely reset
    base = time.time()

    while True:
      time.sleep(0.2)

      sent = time.time() - base
      stuff_float(link, sent)
      link.send(4)

      while not link.available():
        if link.status < 0:
          print('ERROR: {}'.format(link.status))

      response = ''
      for index in range(link.bytesRead):
        response += chr(link.rxBuff[index])

      print('SENT: {}'.format(sent))
      print('RCVD: {}'.format(response))
      print(' ')

  except KeyboardInterrupt:
    link.close()

Arduino:
#include "SerialTransfer.h"

SerialTransfer myTransfer;

char buff[25];
char str[] = "I got this: %s%d.%04d";
float fromPython = 0;

void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {
    //////////////////////////////////////////////
    // handle call from Python
    myTransfer.rxObj(fromPython, sizeof(fromPython));

    char sign = (fromPython < 0) ? '-' : ' ';
    uint16_t integer = fromPython;
    float tmpFrac = fromPython - integer;
    uint16_t decimal = trunc(tmpFrac * 10000);
    sprintf(buff, str, sign, integer, decimal);
    //////////////////////////////////////////////

    //////////////////////////////////////////////
    // send response
    myTransfer.txObj(buff, sizeof(buff));
    myTransfer.sendData(sizeof(buff));
    //////////////////////////////////////////////
  }
}

Verified Python Output:
SENT: 0.20032477378845215
RCVD: I got this: 0.2003

SENT: 0.4077117443084717
RCVD: I got this: 0.4077

SENT: 0.61326003074646
RCVD: I got this: 0.6132

Yet another edit:

Inspired by the answer submitted by OP, I updated the library (1.2.0) to include the member functions tx_obj() and rx_obj(). These will allow you to automatically send and receive nearly any standard Python object types (including lists and dictionaries).
Example Python Code:
import time
from pySerialTransfer import pySerialTransfer as txfer

if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM17')

        link.open()
        time.sleep(2) # allow some time for the Arduino to completely reset

        while True:
            send_size = 0

            ###################################################################
            # Send a list
            ###################################################################
            list_ = [1, 3]
            list_size = link.tx_obj(list_)
            send_size += list_size

            ###################################################################
            # Send a string
            ###################################################################
            str_ = 'hello'
            str_size = link.tx_obj(str_, send_size) - send_size
            send_size += str_size

            ###################################################################
            # Send a float
            ###################################################################
            float_ = 5.234
            float_size = link.tx_obj(float_, send_size) - send_size
            send_size += float_size

            ###################################################################
            # Transmit all the data to send in a single packet
            ###################################################################
            link.send(send_size)

            ###################################################################
            # Wait for a response and report any errors while receiving packets
            ###################################################################
            while not link.available():
                if link.status < 0:
                    if link.status == -1:
                        print('ERROR: CRC_ERROR')
                    elif link.status == -2:
                        print('ERROR: PAYLOAD_ERROR')
                    elif link.status == -3:
                        print('ERROR: STOP_BYTE_ERROR')

            ###################################################################
            # Parse response list
            ###################################################################
            rec_list_  = link.rx_obj(obj_type=type(list_),
                                     obj_byte_size=list_size,
                                     list_format='i')

            ###################################################################
            # Parse response string
            ###################################################################
            rec_str_   = link.rx_obj(obj_type=type(str_),
                                     obj_byte_size=str_size,
                                     start_pos=list_size)

            ###################################################################
            # Parse response float
            ###################################################################
            rec_float_ = link.rx_obj(obj_type=type(float_),
                                     obj_byte_size=float_size,
                                     start_pos=(list_size + str_size))

            ###################################################################
            # Display the received data
            ###################################################################
            print('SENT: {} {} {}'.format(list_, str_, float_))
            print('RCVD: {} {} {}'.format(rec_list_, rec_str_, rec_float_))
            print(' ')

    except KeyboardInterrupt:
        link.close()

    except:
        import traceback
        traceback.print_exc()

        link.close()

Example Arduino Code:
#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {
    // send all received data back to Python
    for(uint16_t i=0; i < myTransfer.bytesRead; i++)
      myTransfer.txBuff[i] = myTransfer.rxBuff[i];

    myTransfer.sendData(myTransfer.bytesRead);
  }
}

Thanks, Luke. Indeed, Serial Inputs Basics was the foundation from which I wrote what I started with - looks like a lot more reading to do with Advanced! I have been using pyserial, but I tried your suggestion by transitioning to pySerialTransfer, using exactly the code in those examples (except the port # of course). After about 2sec, the Mega RX light flashes, but otherwise, I see no feedback on the python terminal; the error, nor the response received. I'm probably doing something wrong, but at the moment, at least pyserial gave some indication there was sending & rec'ving interspersed. Tx!

The example assumed the user was using a second, separate serial port on the Arduino for the Python comms while using Serial for debug prints. I updated the example code and should work flawlessly for you now!

Thanks - updated code based on your example, getting on the right path it seems, but still some issues. Updated question with new code.

I added some blinking of the LED on the board to determine that, despite the python terminal indicating it sent some text, the if statement never evaluates to true.  Code updated to indicate what I've tested; in short, I never get to the blink(60; statement.

@DavidW See my edited answer for a working example that should work for your specific use-case. I successfully verified the exact code with Python 3.7 and one of my Megas.

Beautiful - thank you! Works perfectly. I've added a little more in a subsequent answer to pack other object types. Appreciate your help here.

@DavidW - I edited my answer one more time, lol. I added some helper functions to the library inspired by your answer. Make sure to update your local copy of pySerialTransfer before attempting to use the new funcitons.

Building on P_B's answer to pack additional data types, I extended the python as follows. Of course, the receiving Arduino code needs to receive into the correct data type as well.
def StuffInt(txfer_obj, int_to_send, start_pos=0):
  """Insert integer into pySerialtxfer TX buffer starting at the specified index."""
  return StuffObject(txfer_obj, int_to_send, 'i', 4, start_pos=0)

def StuffFloat(txfer_obj, float_to_send, start_pos=0):
  """Insert integer into pySerialtxfer TX buffer starting at the specified index."""
  return StuffObject(txfer_obj, float_to_send, 'f', 4, start_pos=0)

def StuffStr(txfer_obj, string_to_send, max_length=None, start_pos=0):
  """Insert string into pySerialtxfer TX buffer starting at the specified index.

  Args:
    txfer_obj: see StuffObject
    string_to_send: see StuffObject
    max_length: if provided, the string is truncated to the requested size; otherwise
      defaults to the length of the string
    object_byte_size: integer number of bytes of the object to pack
    start_pos: see StuffObject
  Returns:
    start_pos for next object
  """
  if max_length is None:
    max_length = len(string_to_send)
  format_string = '%ds' % max_length
  truncated_string = string_to_send[:max_length]
  truncated_string_b = bytes(truncated_string, 'ascii')
  print (truncated_string_b)
  return StuffObject(txfer_obj, truncated_string_b, format_string, max_length, start_pos=0)

def StuffObject(txfer_obj, val, format_string, object_byte_size, start_pos=0):
  """Insert an object into pySerialtxfer TX buffer starting at the specified index.

  Args:
    txfer_obj: txfer - Transfer class instance to communicate over serial
    val: value to be inserted into TX buffer
    format_string: string used with struct.pack to pack the val
    object_byte_size: integer number of bytes of the object to pack
    start_pos: index of the last byte of the float in the TX buffer + 1

  Returns:
    start_pos for next object
  """
  val_bytes = struct.pack(format_string, val)
  for index in range(object_byte_size):
    txfer_obj.txBuff[index + start_pos] = val_bytes[index]
  return object_byte_size + start_pos


text:
Arduino voltage connection pins
On the Arduino power connector jack, which is the positive terminal pin and the negative pin?

Center-positive. On the UNO there is a diode, to protect against wrong polarity.

Here is more info about Arduinos power jack, https://learn.adafruit.com/ladyadas-learn-arduino-lesson-number-0/power-jack-and-supply

Arduino's power connector jack's tip is positive while the sleeve is negative but the more important thing to know is what will you be using in powering Arduino? Please provide more information about your setup and possibly a schematic. This will help us understand more what you're trying to accomplish.


text:
Finding address of OLED using I2C communication and Arduino
It is known that address of OLED SSD1306 is 3C. The frame format is as follows:

The figure implies that the binary pattern should be 01111000 for the first frame (considering write mode and the second last bit is a dont care).
So I was trying to send the first frame using Wire.h library. The following is a code
Wire.beginTransmission(0b01111001);
But i receive a nack (return value of 2)
However, If I send 00111100, i receive a ack(return value of 0). What is wrong in my interpretation?

You should scan the bus, maybe the display has a different address. You can use this sketch: https://playground.arduino.cc/Main/I2cScanner/

I referred to this link. It shows the address is 3c but that should not be the case because the above pic is of ssd1306 datasheet

You misinterpret how the Wire library is used. Though the first byte in the transmission is called the address byte, the actual address consists only of the 7 higher bits in that byte. The direction bit is not in the address.
So the Wire.beginTransmission() method wants the address as parameter, without the direction bit. That bit is set corresponding to the used function (0 for Wire.beginTransmission() and 1 for Wire.requestFrom()).
0b0111100 is the real address (when connnecting the address pin to ground)(note, that there are only 7 bits, since the address only has 7 bits). The write operation address byte will then be 0b01111000, though the library is hiding that way from you. You need to provide the 7 bit address to the function.

the second last bit is a dont care

As mentioned above, that is not correct. This bit (the least significant bit of the address) is set by the address pin SA0. It seems, that you have it tied to ground, which sets the corresponding bit in the address to zero. If you would tie it to Vcc, it would be 1.

I understand where I was wrong. Thank you. However, I have one more question. How do I send the read/write bit??

@shivamag000 as chrisl wrote you don't manually send it. The read/write bit is automatically handled by Wire.startTransmission() (clears the bit to address the slave in write mode) and Wire.requestFrom() (sets the bit to address the slave in read mode). It's important to only use the 7-bit address, preferably in another format than binary, which can be a bit confusing

Yes, the data direction bit is handled by the library. When you use the write functions (Wire.beginTransmission() and Wire.endTransmission()) it will use zero for the direction bit. If you use the read function Wire.requestFrom(), it will use 1 for the direction bit.

Also keep in mind, that the actual transmission is done in Wire.endTransmission(). Before that no data will be transmitted.

Thank you @chrisl

I2C has a 7-bit address space. The device's actual address is 0b0111100 (=0x3c). The sequences 0b01111001 and 0b01111000 address the same slave while the first one (least significant bit is 1) starts a read transmission, the second one starts a write transmission.
Those least significant bits are nothing you need to care about when using Wire.h: the mode of operation is automatically set when using Wire.startTransmission(addr) (returns 0 when slave ACK'ed write command) and Wire.requestFrom(addr) (returns 0 when slave ACK'ed read command).

Even if I send 0b01111000, a nack is received

@shivamag000 that's not what you wrote in your question ("However, If I send 00111100, i receive a ack") and a return value of 0 means that the slave ACK'ed

@shivamag000 also, 0b01111000 is not what you are supposed to pass to Wire.beginTransmission(). It takes the 7-bit address. You better don't mess with binary format, simply do Wire.beginTransmission(0x3c)...

can you please show the reference where it says that wire.begin takes seven bit addresses

@shivamag000 https://www.arduino.cc/en/Reference/WireBeginTransmission

Thank you @Sim son


text:
Arduino program using i2c stops working after printing to OLED a few times
A NOTE ON THE PROJECT AND PROGRAM STRUCTURE
I am developing an open source Smart Watch project using Arduino.
The code can be found here: https://github.com/shivangsgangadia/SmartWatch
The code is too large and divided into multiple files, hence I cannot paste it here within the question, hence I request you to look into the github repo.
So far I have interfaced an OLED (128 X 64 SSD1306) and RTC (DS3231 in ZS-042).
I have written libraries for both, which have been included in Github repo.
The program structure allows to add multiple "Modules" which are basically like apps. There is a static State class that holds the program state such as modules to be serviced, and time from RTC.
Each "Module" can be a "App" or "Overlay". Overlays are always visibles, there can be mutiple overlays active, but only 1 app can exist at a time.
WHAT I AM TRYING TO DO ?

Read RTC into State class's static variables
Display once
Attach interrupt to set boolean flag when the RTC gives interrupt (alarm
set to 1 minute) Service interrupt in loop by:

Read RTC into State class's static variables
Reset alarm for RTC
Update display

WHAT IS THE PROBLEM ?
The program works fine 2-3 times, i.e. does what's expected after servicing 2-3 interrupts (hence 2-3 minutes), but after that the print on the OLED becomes mangled and the program stops altogether.
WHAT HAVE I TRIED TO SOLVE IT ?
With Serial.println() in many areas such as before and after OLED::writeString is called in respective classes, I concluded that the RTC is not the issue, but the OLED somehow causes the program to stop.
Removing OLED::writeString statements does allow the rest of the printing to continue for more than 2-3 times, but the program eventually does stop. I have tried replacing the wires and the breadboard, but nothing seems to have any effect.

I can't see anything immediately obvious (kudos to you for your tidy programming style and your lack of anything String related). Chances are it's the I2C communication. It's not great over wires or with breadboards. You can try adding smaller (1kΩ) pullup resistors on the I2C wires.

Thanks for the compliment ! I tried adding 1k pullups and passing the OLED connections through the ZS04 module's extra pinouts and it still doesn't work.

This is wrong in many ways:
String input = Serial.readString();
serialInputBuffer = new char[input.length()];
input.toCharArray(serialInputBuffer, input.length());

What's fatal is that you later don't free the memory allocated with new. Don't use String and new. Both use heap memory and will fragment it with these small allocations until there is no space for the next allocation. I see you have dynamic allocation in other parts of the sketch and there it looks like you have a delete, but they still cause the fragmentation problem.
Use a global buffer like char serialInputBuffer[64]; and use:
int l = Serial.readBytes(serialInputBuffer, sizeof(serialInputBuffer));
serialInputBuffer[l] = 0;

In the scale function, there is a dynamically allocated array. Replace it with a class variable, which acts as a buffer which can hold the maximum number of bytes you expect the use to scale their byte to.
Again, dynamic allocations will cause fragmentation even if the memory is released properly.

I have tried commenting out the whole Serial piece, and it still has no effect.

@ShivangGangadia, you have multiple dynamic  allocations in other parts of the sketch and there it looks like you have a delete, but they still cause the fragmentation problem.

I replaced all dynamic allocations with statics within modules. Still, has no effect at all

@ShivangGangadia, why do you use pgm_read_word to read bytes?

Because the bytes that I need, that is font, are in PROGMEM

@ShivangGangadia, pgm_read_byte?

@ShivangGangadia, you allocate toReturn in scale many times but you don't delete it. (only the last one in writeString)

You were right ! I though I could get away with just one dynamic allocation, but embedded systems are really unforgiving. Please review and approve the edits I have requested so that I can acccept this as the correct answer.

Don't use the Wire library.  If you look closely at twi.c, you'll find it has blocking calls with (potentially) infinite loops.  Eventually a condition will occur that causes one of the blocking calls to hang forever.
See this post and this post for details
Use something like SBWire
Frank

I replaced the Wire library with SBWire. Still no improvement.

OK, so now you are back to basic troubleshooting.  Temporarily abandon your project, and create a new one with just the Arduino and the OLED - nothing else - and the simplest possible code to drive it.

Once you have this simple project working, you'll know right away if the OLED and it's driver are the problem

Did the step by step, will accept the answer by Juraj


text:
Button debounce using millis() in this example
I have been trying to find a way to use millis() instead of delay(), in order to press 2 buttons to turn on and off a blue led.
EDITED:
const int right_button = 8, left_button = 9, yellow_led = 7, blue_led = 6, green_led = 5, red_led = 4;
int previous_left_button_status = LOW, previous_right_button_status = LOW, blue_status = LOW, green_status = LOW;
unsigned long time_setup = millis();
const int delay_task = 250;

void setup()
{
  pinMode(right_button, INPUT_PULLUP);
  pinMode(left_button, INPUT_PULLUP);
  pinMode(blue_led, OUTPUT);
  pinMode(green_led, OUTPUT);
  pinMode(red_led, OUTPUT);
  pinMode(yellow_led, OUTPUT);
  Display.clear();
}

void loop()
{
  int right_button_status = digitalRead(right_button);
  int left_button_status = digitalRead(left_button);
  unsigned long time_passes = millis();
  if (time_passes - time_setup >= delay_task)
  {
    time_setup = time_passes;
    if (right_button_status == previous_right_button_status)
    {
      green_status = !green_status;
      digitalWrite(green_led, green_status);
    }
  }
}

start with the arduino debounce example sketch ..https://www.arduino.cc/en/Tutorial/Debounce

this code does not work is a very poor description of the program behavior ... what actually happens when you run the sketch?

@jstola, my bad for not being specific ;/ my problem here is with both buttons, right/left_button_press are not working as I want them to turn on and off a LED using only delay

you have logic errors in your code .. . using the else keyword creates code that excludes one of the buttons if the other button is pressed ... each button should have a separate if statement

@jstola, so "else if" here means exactly the same as "else",  if a condition is met then do this, and if not(else) do the other one but do not execute the first condition, correct?

@jstola, why is it considered to be a logical error? what if the scenario that I want excludes one condition and activate the other? or do you mean by error, is that if I press right button to turn on a LED, i cannot turn that LED forever because of else if ?

a logic error is something like adding two numbers, when you meant to multiply ... you are monitoring two button presses, but you are excluding a button press under certain conditons because you think that the button press detection is somehow related to the lighting of an LED .... but, the LED lighting and the button press detection are really completely separate functions ... a button press should set a value of a variable, nothing more .... the resulting value can be used to determine if an LED should be lit

Let us continue this discussion in chat.

You've declared the variable for the millis function inside your loop correct and you've declared the delay duration you want to use. Two things you've missed are you've declared 2 variables with the millis function and to use it to control the program flow based on some condition to execute some code, in your case, to press 2 buttons to turn on and off an LED.
The way to to this is to use an if-else statement inside the loop function with one variable declared with the millis function, delay_duration as your reference, and 1 variable declared with a zero value.
unsigned long storeMillis = 0;
const int delay_duration = 500;

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

void loop() {
unsigned long currentMillis = millis();
if (currentMillis - storeMillis > 500) {
storeMillis = currentMillis; //update and store the value of storeMillis for the next iteration
//code you want to do
}

Thank you for your answer, I did somewhat understand your millis(). First, you have an unsigned long which has not been used, you used firstMillis, I think you meant storeMillis in that if condition, correct? Second, how do I use that in a button debounce, I still do not understand the button debounce part using millis()

I suggest that you first change the variables that you used in storing the states of the buttons from true/false to high/low. You've set your variable "left_state" as a boolean wherein you gave it a pin level of "LOW" which is a big no no. Remember that boolean is used in defining logical levels to represent a truth or not while HIGH/LOW is used to represent pin levels in Arduino.

thanks for your explanation, do you mind taking a look at my edited code? millis() is not working in my EDITED part, I still do not know why my right button is not debouncing (going with the flow, everytime I press it) it misses, waits or not turn a led ON

Great, now you need to carefully check if you're comparing the right variables in your condition. Remember that the millis() function starts keeping track of time where you declared it in your code. The variable "time_setup"' is the one that will start counting, say 0 to 5000ms, until the loop function starts. Then that will be the time your variable "time_passes" will start counting, therefore the time value of it must be lesser than the time value of "time_setup".

I suggest that you print these values in the serial monitor for you to know what's actually going on and how it's storing the time in milliseconds.

i really am confused, first you have a variable called secondMillis which was never declared anywhere, and then you did storeMillis = millis(); why didn't you store storeMillis to currentMillis ? ;/

My bad, I edited it already. I was pertaining to the second variable that I declared when I was writing this (which is currentMillis)


text:
NFC library for M24SR64
Im currently working on a project where i build an NFC device and needed some guidance in regards to the library needed for the NFC chip to work on the Arduino IDE. The chip is an M24SR64 chip and i've looked online for the library related to the chip but i couldn't find it. Although i did found a library for the M24SR64-y chip, though i'm not sure if its possible to use it, or whether it will work. If anyone has an idea or any help it would be much appreciated

Here you will find a lib for all M24SR NFC tags
In this test sketch you find details how to connect and test the tag with Arduino. If it helps mark as accepted to help others.


text:
Split string using a delimiter then saving to different variables
I have a string that looks something like this "43;27;42;27". It is the data from 4 DHT22 temperature sensors, i need to splice this string every ";" and save the number to a variable. In the end, I will have 4 variables, each one for every number. Thanks!
The data comes from another esp wirelessly and I need the data in different strings to a nextion display.
I could also change the delimiters to differ from each other, I am posting this question because I am not sure how i should go about writing all of these 4 values in a string then also "decoding" these strings and assigning each one to a variable.

Have you googled for something like "Arduino parse string"?

Was not sure how I would go about googling this, looking into it right now and I post the answer. Thanks!

splice means connect ... the words you want to search are split and parse


text:
STM32duino Can bus library
I couldn't find any library for can bus for STM32duino (Maple Mini) on arduino or even on STMcubeIDE
I found one library on github but it doesn't compile it has a lot of error (its a fork of the stm32duino github library)
I hope that someone could provide a working library or a simple example on how to implement can bus peripheral on STM32F103


text:
MPU6050 Accelerometer freezes/glitches after acceleration
I am trying to do rotational vector calculation using a MPU6050 chip which actually work really well with not too much drift when I rotate the MPU slowly. However, when I accelerate too much, e.g. change direction in my slow rotations or just slightly tap the breadboard with my finger, the values completely go nuts.
I am using an ESP8266 chip to control the chip and I have tried multiple libraries for reading the Gyro/Accelerometer values which all have more or less the same behaviour.
My accelerometer readings from the Serial plotter, before and after the light tap to the breadboard:

Gyroscope does the same thing. The MPU is new (just arrived in the mail few hours ago), I power it using 3.3V and use 3.3V GPIO logic from the ESP chip.
Does anyone know what could be causing this?

I think the key word here is "breadboard". Hardly a stable environment for signals...

@Majenko should I try it on a PCB? I thought so too but why does the problem always occur when the acceleration changes, and immediately goes away after I restart everything?

Probably the sudden change in acceleration makes one of the connections move and communication gets out of sync in some way, or makes the chip get a bad instruction that changes some random setting.

@Majenko Okay, I am going to try to put the circuit on a PCB and see if that helps. Thank you for the suggestion.

@Majenko I have soldered everything now and everything is working perfectly now, thank you so much I have been at this for hours! Thank you very much! It only starts doing this again when I pull so hard on it that the power cable disconnects :D

Your problems are (most likely) related to loose connections in the breadboard. Sudden movements can cause power to be interrupted briefly, or data signals to become corrupted.
Breadboards aren't great for prototyping anything that moves, even slightly.


text:
Serial Moniror, '\r' and Realterm
I'm wanting the results from each of the 6 ultrasound modules to print on their respected line after new results have been generated instead of spitting out a continuous flow (see attached image). I've downloaded Realterm and got the results to show on there as I've read that the serial monitor can't do that but I don't know where to put the '\r' syntax within my script as I have multiple serial.prints to display the data I need.
Here is a section for 1 of the ultrasound modules, they are just repeated for the differing modules.
Thanks in advance for any help!

  //Object Ahead Distance.
  long duration1, distance1;
  digitalWrite(trigPin1, HIGH);
  digitalWrite(trigPin1, LOW);
  duration1 = pulseIn(echoPin1, HIGH);
  distance1 = (duration1/2) / 29.1;

   delay(500);
   if (distance1 >= 40){
    Serial.print("Nothing Ahead, Okay");
    Serial.print(distance1);
    Serial.println("cm");}
   else if (distance1 <= 39 || distance1 >= 29){
    Serial.print("Vehicle Ahead, Slow ");
    Serial.print(distance1);
    Serial.println("cm");}```

\r returns the cursor to the start of the current line. You can't use it to go back up to previous lines.
Instead you need to learn ANSI escape sequences to move the cursor around.
For example Serial.print("\e[2J"); will clear the entire screen. Serial.print("\e[1;1H"); will move the cursor to the top left corner of the screen (the coordinates are \e[{Y};{X}H by the way).
You can also add colour and all sorts of other nice things, none of which the Arduino IDE's "Serial Monitor" can do.
You can find a good reference of ANSI escape codes here.

Thank you, Serial.print("\e[1;1H"); worked a treat


text:
Wireless Bluetooth USB HUB using Arduino nano
I have the following problem/idea:
I have a electronics workbench and a separate PC desk. Now I have a USB HUB on the workbench, but it doesn't properly work, because the USB-cable to the pc is too long. My setup doesnt really allow me to put the PC somewhere else and the USB-hub is already mounted in the closest usable location.
A few days ago I remembered that I have a arduino nano with a hc-05 bluetooth module attached to its hardware serial port. And as both bluetooth and USB are serial connections I was wondering if I couldn't use the arduino sort of as a middle man and connect the arduino via bluetooth to the pc. Then have a software on the pc that registers the arduino as a USB hub with one port and run some code on the arduino that basically makes the arduino act as a USB host (I know that this is possible with the arduino nano) and have it just move data between the USB connection and the bluetooth module.
Im quite sure that all this should be possible. The atmega should even be capable of doing so at or close to maximum USB 2.0 data rates as that is only 12 Mbit/s and it can run at 16 MHz when powered with 5V. Im not quite sure about the maximum data rate for the bluetooth module though, but I can work with a little lower speeds...
The software for the pc could also be relatively straight forward. Something like a virtual USB-port and the software just shifting data from the com-port that is the bluetooth to this virtual USB-port.
So thats the idea. I have some experience in both programming microcontrollers and software for pc.
So what I need is a bit of help with this, as I am not quite sure how to accomplish this.
The parts that I will need the most help with are going to be the programming of the USB host on the arduino and the virtual USB-port on the pc.
The rest should be relatively easy as its basically just shifting data from one register into another.

as both bluetooth and USB are serial connections well, yes, they are both serial, but saying they are anything even remotely alike is like saying that an elephant and a bicycle are similar because they both move forwards and backwards.

You can't. As simple as that. The mere act of thinking about it belies a desperate lack of understanding about how USB works.
Yes, it's "serial" in that it sends one bit after another, as opposed to multiple bits all together ("parallel"), but it is completely unrelated in any way to the "serial" that the bluetooth module or the Arduino speak ("UART").

I agree with Majenko. The best way for you is to buy an active USB extension cable, so that you can handle the distance easily (the signal gets refreshed in the cable by active electronics, so that you can use USB over longer distances).
You consider this to be easy, because you haven't dug into the depth of these topics yet. Here are some important information on that:

Bluetooth and USB are fundamentally different. The term "serial" outside of the Arduino world is just a term for one bit after another. It doesn't describe any protocol or working principle. Interfaces as SPI and I2C are also serial interfaces, but that doesn't mean, that they work similarly, not even in their topology and also not in their protocol behavior. A bridge between these different interfaces is better described as a translator. And translation is always difficult.
Serial in the Arduino world means the UART interface. No similarity to USB or bluetooth.
The Bluetooth spec is rather big. There are many types of connection interfaces, that can be build with it. Examples are the UART (Arduino Serial), HID (like a mouse or keyboard on a PC) or audio (like headphones) interfaces. Each connection has it's specific function. The USB spec is even bigger, way bigger to be precise. You would need to understand how bluetooth and USB work at their core for implementing something like that.
The HC-05 is a chip for getting an UART interface over bluetooth. To change that, you would need to reprogram it with a new firmware. I doubt, that any firmware, that you can find in the web, would be sufficient for your case. Not generic enough. Also the chips hardware is limited, so you can only get limited resources out of it. Most likely you have the HC-05 on an adaptor board, which has a voltage regulator on it (since the HC-05 is a 3.3V device). You would need to ditch that board and solder the chip itself.
The Nano is a bad choice for everything involving USB. The Atmega328p on it, that you program when programming the Arduino, does not have an USB interface. For that the Nano has a second chip, the Atmega32u4, which acts as USB to UART adaptor. You would need to hack it to do anything different than that. Doing it is possible, but you would need to ask yourself, why you are trying to do something so complex with such an incapable board. Also the Nano cannot be an USB host, nor a hub. There is an USB Host shield for the Uno, but that also is limited.
Getting anything even remotely near to 12Mbit/s is illusionary. You won't be able to process nearly one bit every clock edge. You already need several clock edges to do very primitive processing (going into an ISR and then moving the data into a different register, as you put it). And the translation between the protocols will not be that easy. You will need much processing power and also quite some RAM and flash (you will certainly need to buffer some data and the program itself will also be very big to implement something like USB). "A little lower speeds" don't cut it there. Even if possible, that would be painstakingly slow in comparison to a real USB hub.
Most of the software, that you would need for such a project, is non-existent. Doing something that complex with such crappy hardware is an edge case. So you would need to write your own USB stack software. As mentioned, the USB interface is very complex and if you need to ask this question, you are currently not capable of doing this (and neither am I).

I don't say it is absolutely impossible to implement a bit USB functionality with the Nano. But you won't get a satisfying result, that you really can use, even if you were an absolute expert on microcontrollers and the USB and bluetooth stacks (which you really would need to be for it). That is at maximum a project, that an expert would do just for the grind, not for real results.
You have a real life problem, that you want to solve. Choose the easiest way and buy an active USB extension cable.


text:
esp8266 OTA issue
I have uploaded the BasicOTA sketch in Esp8266-12e.
I am written one program, when i try to upload it first time in Esp using the OTA port it gets uploaded successfully, but when i try to upload any sketch after that it does not work.
The console responds with No Answer.
After searching on internet many people have asked to check the sketch size. To check if size matters or not i tried with blinking sketch, and same issue happens there too.
The sketch only gets uploaded in first time.
Can anyone guide me resolving this issue.

the uploaded sketch must use the ArduinoOTA library to handle the next upload

Things to check:

Partition arrangement selected. You have to make sure to keep the same partition arrangement between uploads.
Partition arrangement selected. You have to make sure that the partition arrangement you have chose supports OTA uploads.
You have to reset the ESP8266 manually after your USB upload. You can only do an OTA update to a sketch that has booted in "run" mode, not "boot" mode.
You have the right IP address / hostname selected? (I don't know how that is handled in the Arduino IDE...)
You must upload an OTA-enabled sketch for OTA to continue working.

I honestly believe that this issue is related to the fact that the sketch uploaded through OTA doesn't itself include the OTA code to allow for further OTA upload. For example, the Blink sketch would fail to allow OTA comms as soon as it was loaded. Might want to add another point to your list. I'd post myself, but you've already started a decent troubleshooting list here.

Partition Arrangement Selected-> Do u mean to say flash size ?? its 4MB FS:NONE , OTA:1019kb. 2. How to ensure that. 3. Yes i do reset it manually after uploads. 4. Ip address is confirmed to be correct. i print it on display.

@stevieb Does that mean, i have to include the OTA code in every sketch i want to upload to esp.

@stevieb Good point. Added as point 5.

@javabee Yes, if you don't have OTA code in your sketch then OTA can never work. It's the sketch that provides OTA, not some magic pixie dust.

I think the 5th point has answered my question.


text:
Toggling a blinking led ON & OFF
I am trying to implement a toggle switch to turn blinking ON & OFF. However, the code only turns the led ON or OFF and that too unreliably. Can you help me understand why it isn't working?
   const int redLed = 10;
const int buttonPin = 2;
unsigned long newTime;
unsigned long oldTime = 0;
byte newButtonState;
byte oldButtonState = 0;
boolean ledState = false;
boolean blinkState = false;
boolean state = LOW;

void setup() {
  pinMode(redLed, OUTPUT);
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
}

void loop() {

  newButtonState = digitalRead(buttonPin);
  delay(100);

  // check if button state has changed
  if (newButtonState != oldButtonState) {
    // if button was pushed
    if (newButtonState == HIGH) {
      // check led state
      if (ledState == false) {
        ledState = true;
        blinkState = true;
      } else {
        ledState = false;
        blinkState = false;
      }
      if (ledState == true && blinkState == true) {
        newTime = millis();
        if (newTime - oldTime >= 250) {
          state = !state;
          oldTime = newTime;
        }
        digitalWrite(redLed, state);
      }
    }
  }
  oldButtonState = newButtonState;
}

Also it is not needed to add '== true' for comparing booleans, you can remove '== true' and instead of '== false' you put ! in front of the expression.

Thanks I didn't know that. I have seen a few sketches where they have used booleans without using "==" and I wondered if it's a different notation of if statements. But what if you are evaluating two booleans at once e.g. "if (ledState == true && blinkState == true)" , can you also write them without the == signs?

Yes than you can write if (ledState && blinkState), if you want to write if (ledState == true && blinkState == false) you can write if (ledState && !blinkState)

Cool. Learnt something new. Thanks

I added an answer to show another improvement.

I don't see why you would set blinkState together with ledState. I assume, that you want the button to toggle the blinking. 1 press --> LED is blinking, another press --> LED stops blinking, ...
I suggest to restructure your code. First separate input and output, meaning button check code and LED blink code. For blinking you already have a state variable named blinkState. So in your loop() function you first write
newTime = millis();
if(blinkState && newTime - oldTime >= 250){
    ledState = !ledState;
    oldTime = newTime;
}

That will toggle ledState, whenever blinkState is set, in intervals. Now we simply digitalWrite() that value out directly after that:
digitalWrite(redLed, ledState);

Now we need to handle the button. Your button if statements seem to be good, so we only need to change, whats inside the statements. There we simply negate the blinkState variable:
if (newButtonState != oldButtonState) {
    // if button was pushed
    if (newButtonState == HIGH) {
        blinkState = !blinkState;
    }
}
oldButtonState = newButtonState;
delay(100);

With this code the LED will stop changing and keep the state, that it had, when you pressed the button. If you want the LED to turn off at that point, you shoud add ledState = false; after negating blinkState.
Note, that this code doesn't need your state variable. 2 variables are enough for this. 1 for the current led state, 1 for the blinking state.
Also note, that using delay() is not the best way to debounce a button. It is an easy way, but it might not behave exactly, like you want to. If you want better debouncing, you can use the Bounce2 library from github. If you don't want to use a library for it, you can still learn about their ways to debounce in the Readme file.

Thanks for your very clear explanation. Also the suggestion to break the code makes it easier to follow.

I will try to follow this approach but all these state variables that are interdependent are new to me and at time confusing. I have also read about the concept of state machine and I wonder if it would be easier to code in such contexts

The state variables are not interdependent. You could see both variables to be of a different kind. While ledState directly describes the current output value of the LED pin, blinkState describes an action, which is a bit more abstract. Think of setting one foot before the other, which you could call one step. By changing a fictional state variable like footstate we could change, which foot is the front one, and thus do steps. Then the action "walking" is more abstract, since it is a succession of steps. walking describes the action of successively changing the front foot.

In this case a state variable will not be particular easier to implement. To be exactly: With this code you already have a state machine (as you handle state variables and act upon them). Just not one, that can easily be extended. You can change that to the more extendible version (on the web and on this side are many tutorials about FSMs), though that would be more to make it easier to extend the functionalities. With the current scope of the code you are fine with this structure.

Note, this is not an answer, but I want to show some code examples based on the comment:
You can use as said in the comment:

Remove '== true' in a boolean condition
Replace '== false' by '!' in a boolean condition

You will get this:
  // check if button state has changed
  if (newButtonState != oldButtonState) {
    // if button was pushed
    if (newButtonState == HIGH) {
      // check led state
      if (!ledState) {
        ledState = true;
        blinkState = true;
      } else {
        ledState = false;
        blinkState = false;
      }
      if (ledState && blinkState) {
        newTime = millis();
        if (newTime - oldTime >= 250) {
          state = !state;
          oldTime = newTime;
        }
        digitalWrite(redLed, state);
      }
    }
  }
  oldButtonState = newButtonState;
}

About the following fragment:
  if (!ledState) {
    ledState = true;
    blinkState = true;
  } else {
    ledState = false;
    blinkState = false;
  }

Since you write ledState and blinkState in both clauses, and the condition is simple (so you don't need to put it in a temporary variable, you can replace this fragment by:
blinkState = !ledState;
ledState = !ledState;

Note you have to reverse the order as blinkState depends on ledState.

You never set the pinMode of buttonPin.
Normally it defaults to INPUT if you don't manually specify anything, and I assume from your results that you don't have an external pullup or pulldown resistor.  Therefore you need to specify pinMode(buttonPin, INPUT_PULLUP); and make sure that your switch or button connects the input pin to ground when activated (which means that "active" will be LOW).
Or, if you do have an external pullup or pulldown resistor then it sounds like it may not be wired corrcetly.

There is a pull down resistor in the circuit. I have added the pinMode but it still doesn't work. I suspect it has to do with the conditional statements. I tried changing the "if ledState == true && blinkState == true" to a while and it does start blinking but then it doesn't turn off. I really want to understand what's wrong with my logic here.

Your blink code is only active
if (newButtonState != oldButtonState)

so it won't blink (by itself)
To toggle blinking, just change it e.g. like this
void loop() {
  bool newButtonState = digitalRead(buttonPin);
  if (newButtonState != oldButtonState) {
    // button state has changed
    delay(5);  // debounce
    oldButtonState = newButtonState; // run only once per button push
    if (newButtonState == HIGH) {
      // toggle blink state
      blinkState = ! blinkState;
    }
  }

  if (blinkState) {
     // BlinkWithoutDelay
     unsigned long newTime = millis();
     if (newTime - oldTime >= 250) {
        state = !state;
        oldTime = newTime;
        digitalWrite(redLed, state);
     }
  } else {
     // no Blinking : just leave redLed as is
  }
}

Now please clean up the global variables: some are not required globally, some are not required at all.


text:
Mouse.move values
I understand that Mouse.move move the mouse from its current position, example:
Mouse.move(100, 100);
Will move the mouse to 100 pixels right and 100 pixels down.
But in reality it will move to somehting like 150 pixels right and/or 150 pixels down..
I already tested without cursor precision/acceleration and it doesn't change a thing.
What unit does the function use ?
I know about the 127 -127 limit, and i respect it, but still... when i ask to move 100,100 it doesn't move 100,100.

The mouse coordinates are not pixels. They are a proportion of the physical minimum/maximum parameters of the report descriptor. Since those aren't specified in the report descriptor they are taken to be the same as the logical: -127 to 127.
So moving 100 "units" is moving 100/(127-(-127)) of 100%, which is about 40%.
But 40% of what?
Well, 40% of an inch. Or what your OS believes that an inch is on your current screen.
In the HID specification:

While Logical Minimum and Logical Maximum (extents) bound the values
  returned by a device, Physical Minimum and Physical Maximum give
  meaning to those bounds by allowing the report value to be offset and scaled.
  For example, a thermometer might have logical extents of 0 and 999 but
  physical extents of 32 and 212 degrees.The resolution can be determined
  with the following algorithm:
if ((Physical Maximum == UNDEFINED) || (Physical Minimum == UNDEFINED) || ((Physical Maximum == 0) && (Physical Minimum == 0))) {
    Physical Maximum = Logical Maximum;
    Physical Minimum = Logical Minimum;
}

If (Unit Exponent == UNDEFINED)
    Unit Exponent = 0;

Resolution = (Logical Maximum – Logical Minimum) / ((Physical Maximum – Physical Minimum) * (10^Unit Exponent))

it makes sense, thanks!


text:
Can I run 3 devices on Arduino Uno with different power sources?
I'm pretty new to these types of projects I'd like to work on a greenhouse project with an Arduino Uno. The goal is to be able to sense temperature and control a heating lamp, detect humidity and control a humidifier, and connect a soil hydration sensor and connect a small water pump for irrigation.
Could the Uno support all of this power that could theoretically run at the same time? How would controlling the 3 isolated functions look in the Sketch?

Your question is 2 fold:

Power requirements: The actual power requirement depends on the devices, but the Arduino will certainly not be able to provide power for a heating lamp. It just cannot provide that much current (you would fry the Arduino). But the Arduino is also only powered from outside. I guess you have a power source, that can provide enough power for all the devices. Then you can connect these devices in parallel to the power source (meaning + and - of the heating lamp power goes directly to the power supply). That way the current for the devices doesn't flow through the Arduino. The Arduino will only use control signals, which don't have high current. Sensors are normally either analog sensors (which connect to the analog pins with only neglectable currents) or use communication interfaces, which are also ok. The current hungry output devices (humidifier and heat lamp) either have a digital control pin, a communication interface, or they must be controlled via a relay (depends on the actual devices).
Controlling all the devices: The Arduino can only do 1 thing at a time. But that is no problem, since you can do things sequentially very fast. For example write one function for every device, that you want to control. In that function you communicate with/control the device according to some variables (like the measured temperature). The loop() function can then look as simple as:
void loop(){
    measure_temperature();
    measure_humidity();
    measure_soil_hydration();
    control_humidifier();
    control_headlamp();
}

If you want to only do this periodically (not all the time), you can either add a delay() or - better - use millis() like in the BlinkWithoutDelay example (there are also many tutorials about millis() on the web). Make sure, that the individual functions are not blocking. They should do, what they need to do, and exit quickly. No long staying in loops or waiting for an event there.

Yes, you can run all of those from an UNO, but you'd probably be better off using an ESP32 so that you can add a web portal to your project for relatively the same cost.
You would be able to run the HDT or similar sensor and temperature sensor as well as the hydration sensor directly from an MCU. The other components would require something else, like NPN MOSFET low side power switch (like an FDS3890) that could be controlled by the MCU. You will need to look at the datasheets for each component you buy, find the power ratings, and make sure you have components rated to support the voltage and current of your devices (A good rule of thumb is twice the expected use, so if you have a 12V pump that can sink 3A of current, you should get a MOSFET that can handle 24+ volts and 6+ Amps.
Each sensor will likely have a library you will use and has samples. Googling each one and working on one individual function at a time is a great way to learn and progress your project.
Some MCU only have one core and everything is placed into a loop. Others (like that ESP32) have multiple cores, and can use a RTOS for task scheduling.


text:
Can a video game potentially detect arduino leonardo?
If I automated an action in a video game through arduino leonardo, can it be detected? Things like autohotkey can be easily detected, however i would expect an arduino would be far more difficult. How easy/difficult would it be detect?

it all depends on the game, and on the controller that you are emulating ..... for example  if the game is a first person shooter and the arduino is pulling the trigger exactly every 95 ms then the game may be able to determine that you are not pressing the keyboard manually

It would be little use to only check for Arduino's. You would in some way have to check the player's behaviour and estimate if it's 'human', which works for any type of automation.

Nigh on impossible. True the game could look to see if there is a specific VID/PID combination visible to the computer, but that is probably not going to happen (and anyway you can change it).  As far as the game is concerned, input from a keyboard is input from a keyboard, whether that keyboard has buttons or a piece of code it really can't tell.

Yes.
First you'll need to define how you plan to inject the new input signal, into the data "packets" as a spoof of controller signals, or just jumping the switches?
In the context of any modern gaming console, it could be detected. Easily. Consoles and controllers use any number of proprietary protocols which sync.commands to improve response and reduce controller lag. If you're just jumping the switches, then no, you could simulate hadouken and probably get away with it just fine.
If you're referencing PC gaming, then that would be hard if not impossible with the variance of input control available.  The best deterrent would be the security of the game software itself and the genre of the gaming. Some games actively encourage Hotkeys.


text:
Clearing string buffer with memset after a serial read
In using the SerialTransfer.h / pySerialTransfer libraries to send commands between my laptop and an Arduino Mega, I am sending multiple sequential strings between the devices. However, I'm having trouble "clearing" the receiving buffer on the Arduino side - it never shrinks, despite a few different attempts to clear the string (memset; a for loop).
I'm sending a string to the Arduino of the format , where there are anywhere from 1 to 5 asterisks.  Then the Arduino is simply sending the exact same string back, without any processing (as of yet).  And in the python terminal, I'm printing it all out; this is what I get:
SENT (17 bytes): <rand_len_str=**>
RECD (17 bytes): <rand_len_str=**>

SENT (18 bytes): <rand_len_str=***>
RECD (18 bytes): <rand_len_str=***>

SENT (19 bytes): <rand_len_str=****>
RECD (19 bytes): <rand_len_str=****>

SENT (17 bytes): <rand_len_str=**>
RECD (19 bytes): <rand_len_str=**>*>

SENT (18 bytes): <rand_len_str=***>
RECD (19 bytes): <rand_len_str=***>>

SENT (18 bytes): <rand_len_str=***>
RECD (19 bytes): <rand_len_str=***>>

As long as the string is growing, all is well - but see the error in the 4th pair, with the extra *> characters, etc.
The following is my Arduino code; I've tried to reset the receiving string using memset, but this seems not to be working.
#include "SerialTransfer.h"

SerialTransfer myTransfer;

const int CMD_LEN = 200;
char buff[CMD_LEN];
char received_str[CMD_LEN];

void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {
    //////////////////////////////////////////////
    // handle call from Python

    memset(received_str, '\0', CMD_LEN*sizeof(char));
    myTransfer.rxObj(received_str, CMD_LEN);

    sprintf(buff, "%s", received_str);
    //////////////////////////////////////////////

    //////////////////////////////////////////////
    // send response
    myTransfer.txObj(buff, strlen(buff));
    myTransfer.sendData(strlen(buff));
    //////////////////////////////////////////////
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

I didn't see anything in SerialTransfer.h about clearing the rxObj; I can always just use the first terminating > character to parse the command - but I imagine there is a cleaner / better solution in clearing the buffer, or at least, I'd like to understand what's going on! Thanks in advance.

what mean '\0' in this line? memset(received_str, '\0', CMD_LEN*sizeof(char));

Instead of clearing your buffers, make use of the bytesRead property.  Have a look at how they print the received string in the example code from the library using a for loop.  I don't know that it is null terminated or anything.
Example from the library's github page:
#include "SerialTransfer.h"

SerialTransfer myTransfer;

void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);
}

void loop()
{
  if(myTransfer.available())
  {
    Serial.println("New Data");
    for(byte i = 0; i < myTransfer.bytesRead; i++)
      Serial.write(myTransfer.rxBuff[i]);
    Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }

Thanks for the pointer - that did the trick.  Applying it to my original code, if I update the few lines around handle call from Python to the following, it works as intended.
    //////////////////////////////////////////////
    // handle call from Python

    myTransfer.rxObj(received_str, CMD_LEN);
    strncpy(buff, received_str, myTransfer.bytesRead);
    buff[myTransfer.bytesRead] = '\0';

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

Thanks again!


text:
Controllino Mega and Fatek HMI
I have a setup that controls the rotation of two stepper motor using Arduino UNO, HBS860H stepper drivers, 4X4 keypad and LCD screen. I have replaced the Arduino Uno by a Controllino Mega and it works good. Now I am trying to replace the Keypad and LCD screen by a FATEK HMI PN2043NK.
I have the sketch for the Controllino,
I can use RS485 to communicate both devices.
I use FV Designer to program the HMI, but I don't understand how to run the sketch from the HMI.
I need some help with a simple example Please, any help I could use to start learning to communicate the HMI with the Controllino and run the steppers will be welcome.

I am unfamiliar with those devices, but I would assume you write software for both which uses RS485 to send messages between them. It'll be up to you what those messages are and what they mean, and how you respond to them.

The usual "sketch" is "always" running on your arduino (Controllino) unless it is put into a non-run mode (like when loading a program) or doesn't have power.  What you need in your sketch is to do something IF a command is received on the serial (RS485).  Rather than simply running the command you want, the sketch needs to check the serial and only execute the command if the HMI sent the correct signal.
For motor control, you could use G-code where your HMI sends G-code move commands over RS485 and your Controllino executes them.  A handy RS232 example is grbl.