text:
I2C Devices Interference
I am currently trying to connect 3 I2C Devices to an Arduino Mega, as detailed in the fritzing sketch. The Sensors are: Max86150 PPG Sensor on a breakout board (5v), MLX90614 IR Temperature Sensor (3.3V) and a SM9336 Pressure Sensor(3.3V). Essentially I can connect all devices and read off the sensors using individual sketches, but when I combine the sketches the values are not consistent and then the sketch crashes after only a few seconds.
Weirdly enough, when I combine a sketch with either the Temperature sensor and the Pressure sensor or the Temperature Sensor and PPG Sensor, it will work. But Pressure and PPG do not work together.
Does anyone have any idea what could be happening? I did have it working for a small while with some different wires, could this have anything to do with it? But even still some results I was reading from the sensor were the error values (e.g. the value you get when there is nothing connected, but it wasn't crashing). For reference I am using 30 AWG wires and strip board instead of the breadboard in the Fritzing.
//PPG
#include "max86150.h"
MAX86150 max86150Sensor;
uint16_t ppgunsigned16;
uint16_t irdata;

// Pressure Sensor
#include <Wire.h>

#define PressureSensor_Data 0x30 // Pressure Register address
#define TemperatureSensor_Data 0x2E // Pressure Temp Sensor Address

int P0,T0,P1,T1;
int SMD993Address = 0x6C; // Device Address

//Timing
#define INTERVAL 10 //10 milliseconds per sample for 100 Hz, change this for different sampling rates.
uint32_t lastMicros = 0;

// Temp
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();

void ppgsetup()
{
  max86150Sensor.setup();
}

void PPG() {

while (1){
 if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);

        Serial.println(ppgunsigned16);
  //ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
  //Serial.println(ppgunsigned16);

  if (ppgunsigned16 > 7000){

     for (int z = 0; z <= 500; z++){//This takes a reading every 10 milliseconds for 5000 milli seconds which is 5 seconds, 500 readings
       digitalWrite(ledPin,HIGH);//turning LED on
        //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 100th of a second
            //lastMicros = micros(); // do this first or your interval is too long!

            if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
        irdata = (uint16_t) (max86150Sensor.getFIFOIR()>>2);

        Serial.print(ppgunsigned16);
        Serial.print(",");
        Serial.println(irdata);
            //Serial.print("Check PPG");Serial.println(y);
            //mySerial.write(84);mySerial.print(ppgunsigned16);mySerial.print("/");
            //mySerial.write(83);mySerial.print(irdata);mySerial.print("/");
    }
    }
    digitalWrite(ledPin,LOW);//turning LED off
    break;

}
}
}
}

void spirometry() {

    for (int x = 0; x <= 500; x++){
    Wire.beginTransmission(SMD993Address);
    Wire.write(PressureSensor_Data);
    Wire.write(TemperatureSensor_Data);
    Wire.endTransmission();
    Wire.requestFrom(SMD993Address,2);//This takes a reading every 100 milliseconds for 10000 milli seconds which is 10 seconds

    //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 1000th of a second
      //lastMicros = micros(); // do this first or your interval is too long!

    if(Wire.available()<= 2) {
    P0 = Wire.read();
    P1 = Wire.read();
      }

    int Ptotal = P0 + (P1<<8); //The high byte is transmitted second so that

    Serial.println(Ptotal); // Print Ptotal to the serial monitor
    //mySerial.write(81);mySerial.print(Ptotal);mySerial.print("/");// Send PTotal over BLE with flag 81, this will change as sending via bytes is more efficient

    }

  }

void temperature() {
  for (int y = 0; y <= 10; y++){
      mlx.begin();
      Serial.println(mlx.readObjectTempC());
      mySerial.write(82);mySerial.print(mlx.readObjectTempC());mySerial.print("/");
      delay(10);
}
}

void setup() {

  // BT
  mySerial.begin(9600);
  Serial.begin(9600);//Sets BT Serial Comms to 115200, ensure that BT is allowing for this
  //LED
  pinMode(ledPin, OUTPUT);
  // PPG
    // Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }
    Serial.println(max86150Sensor.readPartID());
    ppgsetup();

  //Pressure Sensor

  //Temp

  //Sleep
  sleep();

}

void loop()
{
  // put your main code here, to run repeatedly

   PPG();
   delay(10000);
   spirometry();
   delay(1000);
   temperature();

}

Have you tried adding pullup resistors to the lines? As you put more devices on the bus, the capacitance is rising. Pullups (maybe 4.7kOhm, which I mostly use for I2C) may help with that. Also: How long are your wires? I2C is made for rather short connections in the single digit cm region. Long wires can make it unreliable.

It might not be a good idea to totally spam the bus with your messages (for example you take readings very rapidly in spirometry(). Please try to introduce a small delay or similar there. And why do you call mlx.begin() 11 times for reading the temperature? Wouldn't one begin in setup be enough?

@chrisl I've been running I2C devices over 10m cable, with only occassional read errors, so that's unlikely the problem here. Are the device addresses unique?

@chrisl AFAIK there are internal pullup resistors within the Arduino, but I will give them a try and see if it works any better. The cables are probably 10 cm max, most would be in the single cm range.
I have tried playing around with the delays but it doesn't seem to change anything, I am trying to achieve a 100 hz sample rate, which I have read should be achievable on the Arduino Mega. The Mlx.begin() is in the wrong location, good spot I will move that.

@PMF Yes all addresses are unique, what wire gauge are you using for 10m?

@TeeGallagher It was a 8x 0.25mm2 data cable. I used 2 wires for ground, 1x 5V, 1x 3.3V, 2x for I2C. The remote end has a 4x20LCD, a temperature sensor, a GPIO expander with a few buttons and LEDs. The main problem is actually that the 3.3V are not really stable on the far side.

You start Wire in High Speed mode for ppg. You did not set that back, when performing Wire access for pressure. Can the pressure sensor handle high speed mode? Your code is quiet unreadable to me, so it might be, that I've overseen something.

@PeterPaulKiefer This looks like it could have worked, I had to replace a wire because it broke but this seems to have solved the issue. So great spot thank you, I pulled that line of code from an example and I thought it was belonging to a library. Serves me right.

I had a similar problem sometime ago, where I attached 2 servo driver boards and a battery hat (that used I2C for reading power levels) to a Raspberry Pi. The battery board worked alone and the servo boards worked alone, but when all three were present, the battery board stopped working. And all had unique addresses. After a few hours of going nuts, I realised that there were pullup resistors on the pi and all three boards attached. The total resistance of all 4 parallel pullup resistors were out of spec for I2C. I removed the resistors from the servo boards and everything started working together. So maybe you could disable the pullups on all baords except the Arduino and see if that is the problem.

Thanks for the response, it seems to be that I had unknowingly set the I2C Wire Interface to High Speed and that it was essentially crashing the pressure sensor and the sketch, as far as I can tell anyway.

@TeeGallagher, I voted this up because it was a good answer anyway.  If you have some confidence that your high-speed rate was the problem, you should make a separate answer and later accept it.

As pointed out by @peterpaulkeifer; Here
// Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }

I was setting the I2C Speed of the I2C Interface bus to fast and it seems that the pressure sensor was not able to handle this and would therefore give error answers and then crash.


text:
RTClib now() within while loop does not update
I ran into this while trying to make a battery monitor and wondered where I went wrong. Using RTClib available in the Arduino IDE or from adafruit github, I ran into problems when trying to call now within a while loop inside of loop.  Here is a simple example:
#include "RTClib.h"

#define ledPIN 13

RTC_PCF8523 rtc;

void setup() {
  // put your setup code here, to run once:
  pinMode(ledPIN, OUTPUT);
  digitalWrite(ledPIN, LOW);
  Serial.begin(9600);
  while(!Serial) {/* wait for Serial */}
  rtc.begin();
  rtc.start();
  digitalWrite(ledPIN, HIGH);
 }

void loop() {
  // put your main code here, to run repeatedly:
  char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
  while (millis() < 60000){
    Serial.println((rtc.now()).toString(fmt));
    delay(5000);
  }
  Serial.println("Finished");
  digitalWrite(ledPIN, LOW);
  while(1) { /* do nothing forever */ }
}

The output of this little test will be the same time repeated every 5ish seconds.  If it matters I am using a Feather M0 with the FeatherLogger that has an RTC on it.  Changing this loop function to this:
void loop() {
  // put your main code here, to run repeatedly:
  char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
  if (millis() < 60000){
    Serial.println((rtc.now()).toString(fmt));
    delay(5000);
  } else {
    Serial.println("Finished");
    digitalWrite(ledPIN, LOW);
    while(1) { /* do nothing forever */ }
  }
}

shows that now does in fact update the time every 5ish seconds.  I looked at the code for now and it appears to do very basic i2c commands to get the time and report it back.  The only thing I can think of is that the compiler created a (not so) temporary DateTime object for me within the while loop and the RTC library does not provide a convenient constructor or operator to overwrite the existing object.
I tested my theory with this
void loop() {
  // put your main code here, to run repeatedly:
  char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
  while (millis() < 60000){
    DateTime t1 = rtc.now();
    Serial.println(t1.toString(fmt));
    delay(5000);
  }
  Serial.println("Finished");
  digitalWrite(ledPIN, LOW);
  while(1) { /* do nothing forever */ }
}

But again, the time did not change so clearly I don't understand what's happening here.  Why doesn't the rtc now function work as intended within a while loop inside the loop function?

if (! rtc.begin()) {     Serial.println("Couldn't find RTC");     Serial.flush();     abort();   } can you add this part to your code to check whether it is giving any error or not

You have also not added the date and time in your code. Before going forward can you check whether the example code is working or not

Try changing your loop to while (millis() < 60000){  volatile DateTime time = rtc.now(); Serial.println(time.toString(fmt)); delay(5000);   } If this works, your theory about a wrong compiler optimization is correct.

See the documentation of DateTime::toString():

The buffer parameter should be initialized by the caller with a
string specifying the requested format. This format string may contain
any of the following specifiers: [...] The specifiers within buffer
will be overwritten with the appropriate values from the DateTime.
Any characters not belonging to one of the above specifiers are left
as-is.

The important thing to realize is that the buffer parameter is used
both as input (for the format description) and as output (for the
formatted date and time). You initialize it with a format description
("YYYY/MM/DD-hh:mm:ss\n"). Then, after the first call to toString(),
the same buffer contains the formatted date and time. It does not
contain the format description anymore. On the second call to
toString(), as per the rule “Any characters not belonging to one of
the above specifiers are left as-is”, the buffer is not modified.
Solution: Put the buffer initialization within the same while loop
as the call to toString().

As usual, reading the documentation would have saved the OP a lot of time... ;-) +1

source: Stack Exchange

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

sort: votes


text:
changing bitrate of audio recording and taking samples from audio in arduino
I am looking to make a baby cry detection module that is a part of a bigger project i.e. IOT based baby monitoring system. Using AI, i have a dataset (of baby crying and not crying) to train model using binary classification through logistic regression. The problem is that the dataset has a 10kbps sample rate. and arduino records audio on 192kbps probably. so i need the arduino recorded audio to be 10kbps. secondly i need 100 weights or samples from the arduino recorded audio. so lets say the audio is of 5 seconds, so i need a sample after every 50ms so that the total samples would be 100. the main problem is i don't know how to take samples from an audio being recorded or a prerecorded audio using arduino. The 100 samples would then be multiplied by the 100 samples from the trained model and then added and then sigmoid function will be used so that at the end we can know whether the baby is crying or not. All the deployment of the model will be done in arduino. Any help regarding taking the samples or bitrate, would be much appreciated. Thanks in advance! :)

“kbps” means kilobits per second. That is a unit of bit rate, not of sample rate. If you want help for controlling the sampling rate of the Arduino, tell us what sampling rate you need, and what model of Arduino you are using.

What arduino are you using that can sample at 192ksps?

With what exactly do you need help? Do you already have a code, that samples the audio and sends it to the rest of your setup? Or are you starting from zero in this part?

@EdgarBonet what i need at the end is 10kbps arduino recording quality or to convert any kbps into 10kbps. i am using arduino mega and node mcu. finally will be working on either one. thanks

@Majenko i have heard that arduino recording quality is 192kbps, i have not tested it yet. thanks

Where did you hear such nonsense?

@chrisl at the end of the day, i need 100 samples from the recorded audio on the arduino. it can be real time which means arduino just records the 100 sample values and not the audio, or it can be post processing which means that first arduino records the audio and then extracts 100 samples from that audio. either ways i need 100 samples. so that then the 100 samples can be done some calculations on, to finally deploy the model on arduino to check whether baby is crying or not. thanks

@Majenko kindly guide, I am fairly new to arduino and this is my Final Year Project at the university. thanks

Well, firstly the Arduino (as in most basic 8 bit Arduino branded boards, the most common type) really do not do audio. Maybe very low quality, brief, scratch sounds, but not proper audio. Secondly the absolute maximum sampling rate of a single ADC channel  is 9615Hz.

Thirdly most Arduinos have such a minuscule amount of memory there's no way you'll ever get multi-second sampling to fit into it.

@Majenko i am confused in Hz and kbps. secondly i know arduino don't have much memory thats why i will be using a memory card reader along with it. i have seen tutorials on how to record audio with arduino on memory card. Moreover, i was thinking what if i directly attach a microphone on A0, and get the analogRead out of it after every 50ms. that will make 100 samples but i doubt that'll work. thanks

1Hz is one sample per second. 1000Hz is 1kHz and 1000 samples per second is 1ksps. One sample consists of a number of bits depending on the resolution. The bps is the bits per second, or the number of bits per sample multiplied by the number of samples per second.

What are you actually trying to achieve? Don't tell us what you think you want to do, but tell us what you want to achieve as the end result.

If you take 1 sample every 50ms that is a sampling rate of 20sps. According to Nyquist-Shannon theorem that means you'd have a maximum detectable frequency of 10Hz. I fail to see how that would be of any use unless you're a blue whale.

@Majenko thanks for the valuable information. i am actually trying to train a model for baby crying detection. and then deploying that model on arduino. since many machine learning algorithms require heavy processing power for deployment, but logistic regression method is very lightweight to deploy. in this method we take 100 samples from recorded audio on arduino, and 100 weights from the trained model from dataset. then we multiply these two and then add them. and then apply sigmoid function. then give a threshold of 0.5. the result will be a numerical value and will tell whether baby crying

@Majenko yes that will be 20SPS and we will have 100 samples for a 5 second audio

@Majenko, Baby whale doo doo doo doo doo, baby whale doo... there, now it's stuck in your your head.  Thanks for that.

First of all, I am pretty sure your idea of using discrete ADC samples
as predictors for your model is hopelessly naive. As explained by
Majenko, you cannot expect anything meaningful from a sound recording
taken at 20 samples per second. You may have more luck using
spectral intensities as predictors. I suggest you start by doing some
time–frequency analysis on your training data, just to get some ideas on
what predictors may be worth trying. In any case, I strongly suggest you
train and test your model on your computer, before committing any
code to the Arduino.
That being said, sampling a signal at 20 Hz is quite easy: wait for
50 ms (or 50,000 µs for better accuracy), take one sample,
repeat. The only caveat is that you have to use millis() or micros()
rather than delay() or delayMicroseconds(), otherwise the sampling
period will be longer than expected because of the time needed to
execute the code.
Applying the sigmoid function just to compare the result to 0.5 makes
little sense. You know the sigmoid is larger than 0.5 only when its
argument is positive, so you can trivially save yourself expensive
floating point operations.
Here is a tentative implementation of (my understanding of) the idea you
suggest:
const uint8_t mic_pin = A0;
const size_t sample_count = 100;
const uint32_t sample_period = 50000;  // 50,000 us = 50 ms
const int weights[sample_count] = { 12, -42, 23 /* etc... */};

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

void loop() {
    // Record the samples.
    int samples[sample_count];
    uint32_t last_sample = micros();
    for (size_t i = 0; i < sample_count; i++) {
        while (micros() - last_sample < sample_period) { /* wait */ }
        samples[i] = analogRead(mic_pin);
        last_sample += sample_period;
    }

    // Compute the weighted sum.
    long sum = 0;
    for (size_t i = 0; i < sample_count; i++) {
        sum += (long) samples[i] * weights[i];
    }

    // Predict.
    if (sum >= 0) {
        Serial.println("The baby is crying!");
    }
}

surely i am looking into more methods of machine learning, the big downside of the rest of the models is that they cannot be deployed on arduino. And yes i have looked into spectrograms, they are much more valuable. thanks alot for the information and the code you provided :)

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


text:
Arduino send commands fast
I need cnc machine to run as smooth as possible.
It receives commands like this "M_XY 10.233 20.123".
If i send command by command there is a slight delay between commands and its noticeable.
I set serial timeout to 5 ms.
I tried to send n commands and store them on arduino, but arduino cant store much in ram. There is a huge delay while sending n commands.
I was thinking about converting letters (machine writes letters) to bezier and sending arc by arc or letter by letter in arcs. Can atmega328p interpolate bezier fast enough?
Would it be faster if i send numbers in bytes instead of strings?
That would be 4 bytes per float and merge with union on arduino.
Is there any better way of doing this i don't know of?
Edit:
This is how string commands are processed.
void addCommByte(const byte b){
  if(commID == MAX_COMM+1){
    commID = 0;
    Serial.println("TOO LONG COMMAND");
    Serial.flush();
    return;
  }

  if(b == '\n'){
    comm[commID] = '\n';
    commID = 0;

    processCommand();
  }
  else if(b == '\r')
  {
    commID = 0;
  }
  else
  {
    comm[commID++] = b;
  }
}

void loop() {
  Serial.flush();
  while(Serial.available() > 0) {
    addCommByte(Serial.read());
  }
}

Edit. Way better way.
C# side. Check for endianness in c#. Arduino is little endian.
        public void MOV_X(float mm)
            {
                SendCharAsByte("q"[0]);
                SendFloatAsBytes(mm);
            }
        public void SendFloatAsBytes(float f)
        {
            byte[] vOut = BitConverter.GetBytes(f);
            serialPort.Write(vOut, 0, 4);
        }

        public void SendShortAsBytes(short f)
        {
            byte[] vOut = BitConverter.GetBytes(f);
            serialPort.Write(vOut, 0, 2);
        }

        public void SendCharAsByte(char c)
        {
            byte[] aaa = new byte[1];
            aaa[0] = (byte)c;
            serialPort.Write(aaa, 0, 1);
        }

Arduino side.
void loop() {
  while(Serial.available() > 0) {
    processV2(Serial.read());
  }
}
// from processV2
if(byt == 'q'){   // mov x
    float mm = readFloat();
    if(X_DIR == 1) mm *= -1.0;

    stepperXY.moveXForMMSync(mm);
    Serial.println("p");
    return;
  }
// merge bytes
union u_tag {
   byte b[4];
   float fval;
} u;

float readFloat(){
  Serial.readBytes(u.b, 4);
  return u.fval;
}

There is no need to flush serial.

If you're receiving the serial data properly then there is never any need for a serial timeout. You shouldn't be relying on Serial.parseFloat() and such functions.

I'm using String c = Serial.readString(); in loop.

And therein lies your problem. You are reliant on a timeout. Instead you should be looking for the end-of-line character and reading the data up until you see that. And also don't use String as that will cause your system to crash randomly.

https://majenko.co.uk/blog/reading-serial-arduino

Please include a compilable minimal example code in your question. You can cut out all the CNC parts and just leave the Serial communication code. Please make sure, that the code is still compilable

I switched to char by char and its faster. Delay is still noticeable.

Why are you flushing Serial in loop? As I remember, firmware like GRBL also uses ASCII based communication to directly send the gcode to the CNC. So that can work. What are you doing to process the command? Are you measuring the delay between sending the command and the motor moving? How long is it now?

I did Boggyman's idea. There is still slight delay, but its acceptable. I'm using thread for command sending and receiving commands loop. That delay might be coming from c# thread.sleep loop. Somewhere i read that thread cant sleep less than 12 or so ms. Something windows os related.

If you have an existing CNC, you may have to abide by its comm protocol.  Otherwise, if the Arduino is part of a CNC you are building, and it is supposed to accept commands from a host computer, the first thing to do is make sure your baud rate is set higher than the default.  I have found 115200 to be a good choice for stability.  Next, you should avoid sending TTY-type text strings, and send binary values instead. You'd send an initial byte or word to specify the command type, followed by the data.  In my open-source DaqPort sketch for high-speed data acquisition https://www.daqarta.com/dw_rraa.htm I use the high nybble of the command to specify the general type, and the low nybble to specify more detail like channel number.  The sketch uses a big loop with if(Serial.available() > 0) to read the first byte, and a switch/case to determine what to do.  The the specific command reads the proper number of bytes and does whatever.  This is way faster than having to parse text and convert to binary.


text:
Reading bits from a const char pointer
I'm getting a bit tripped up on const char pointers lately.
I'm getting a message from a server that comes through as either a c style string, a standard library string, or a WString:

I'm sending down a buffer of 32bit values from my server that aren't ascii or utf text, they're just bit values I want to parse and read on the esp32 side:

I thought "oh, I'll just mask the bit values 32 bits at a time and right shift the data to get the message (in reverse order, but still I can work with that). The problem that I'm running into is that I can shift numbers but not strings or byte arrays.
I wrote out a function to allow me to grab a piece of the string 32 bits at a time and convert that into a number while using an offset:
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{

  uint32_t payload = 0;
  for (uint8_t i = 0; i < 8; i++)
  {
    payload <<= 0;
    payload += data[i + offset];
  }
  return payload;
}

But when I try to grab the first couple of 32 bit chunks the data isn't what I expected:
void handleGameFrame(const char *data, uint32_t length)
{

  uint8_t phaseAndColission = get32BitInt(data, 32);
  uint8_t player = getByte(data, 32 * 2);

  Serial.print("data: ");
  Serial.println(data);
  Serial.print("phaseAndColission: ");
  Serial.println(phaseAndColission, DEC);
  Serial.print("player: ");
  Serial.println(player, DEC);

}

yields:

I know the Serial.println(data); isn't going to output anything b/c it's a c-string of non-printable values, but the other chunk grabbing isn't giving me the same output from my server. It's hard to verify everything without being able to see all of the bits in the overall data pointer and I think I tied myself in (another) knot.
Is there a good way to parse 32 bit values out of a const c-string?

"they're just bit values". You mean, they're just uint32_t that are being pointed at with a const char * ?

Oh, I just mean data (the const char *) holds bits in it that can't be Serial.println-ed because because even in 8 bit form they're not ascii/utf valid characters so nothing goes to the monitor.

but yeah, data is a c-string of bytes and I know that I want to interpret it as 32 bit integers, I just can't figure out how to do it.

Well, "c-string" basically means zero or more non-'\0' followed by '\0'.  If any of your numbers happen to have a zero byte in them, that will terminate the "string" before the end of your actual data. E.g. 0xAA00BB.  It's really just not a string at all.  In terms of how you get the data out of it, if it's properly aligned for uint32_t, you can just const uint32_t *ui32p = reinterpret_cast<const uint32_t *>(mycharptr);  If it's not aligned, you would do something like memcpy it into an array or individual elements into a single uint32_t variable.  There's nothing really "Arduino" here.

might have to hex encode the values to transmit them.

it looks like a X->Y problem. "I'm getting a message from a server that comes through as either a c style string, a standard library string, or a WString" why?

@Juraj those are the message formats that the library I'm using gives me. There's not an option for just a buffer of bytes. I would think that the c-string is the equivalent of the buffer, but there's the null terminator issue.

You wrote:

I wrote out a function to allow me to grab a piece of the string 32
bits at a time and convert that into a number while using an offset

This function is almost correct. Try this:
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{

  uint32_t payload = 0;
  for (uint8_t i = 0; i < 4; i++)
  {
    payload <<= 8;
    payload |= data[i + offset];
  }
  return payload;
}

Compared to your version, the differences are:

It reads 4 bytes instead of 8, as 32 bits are four bytes.

For each byte being read, it shifts the payload by 8 bits (i.e. one
byte) instead of zero. Shifting by zero has no effect.

It uses |= instead of +=: just a micro-optimization for the sake
of 8-bit MCUs. It shouldn't make much if a difference on a 32-bit
micro.

Oh my god. I can't believe I missed that bit shift by zero :facepalm: I know the for loops conditional check is also wrong, but I can't believe I missed the shift error. Thanks for pointing those out and also the bitwise or optimization. I appreciate you taking the time to correct the function :bows:


text:
Sense person connected to TENS unit
So let's say I use a store-bought TENS unit for liability. I want to make a challenge where you need to hold on to the TENS unit for 10 seconds before it activates a solenoid. How can I have an Arduino detect if someone is touching some metal posts connected to the unit? Would I need to measure the current for the tens unit or something? Any ideas/suggestions? Thanks!
Edit- Not sure if this should be in Arduino or Electrical Engineering, feel free to move it.

@jstola one of those things you connect to your body with sticky pads that shocks you and contracts your muscles. They are supposed to help with muscle pain and such. So basically it shocks you safely.

I think the main problem here is that you want to measure in the presence of high voltage from the TENS. Not having experience with TENS circuits, I would suppose that their contact pins are connected to the high voltage source through resistors to limit the current. (Or some equivalent current-limiting scheme.)  If so, the voltage between the contacts should drop when there is a person connected. You should be able to detect that drop with the Arduino.  The "obvious" approach would be to use voltage dividers to reduce the no-load voltage to less than 5V so the Arduino ADCs can handle it. You'd need high-value resistors in the dividers so they don't load the TENS... maybe 1 Megohm or more for each divider.  One problem with this simplistic approach is that the TENS is putting out its stimulus using brief pulses, which may be too quick to catch with the ADCs.  To get around that, you'd feed the output of each divider through a diode to an R-C filter.  (Note that you need the diode anyway, since the TENS output is probably AC and the Arduino ADCS only want DC.)  This may take a fair amount of experimentation to get the values right, which you should do without the Arduino... just a DVM or scope that you can start at a high-voltage range until you sure you have everything worked out to 0-5V.


text:
Problem with my usb plug
First of all, we connected our usb plug to arduino board (starter kit). After that, we completed Project 1 successfully (circuit with led and switch.) We tried unplug the usb cable, but it was very difficult, we had to pull very hard, but we couldn't unplug it. Finally, I managed to take it away with the help of my partner. I was pulling the usb and my partner was keeping the arduino board stable. The result wasn't very nice, we probably broke the usb cable. You can see what I mean in these images, the metallic coating part of the cable is still stuck on the board.
https://ibb.co/6wtf02J
https://ibb.co/4pZg2w0
https://ibb.co/WPchtgN
https://ibb.co/gPHZYnt
Nevertheless, we put the remaining cable back where it was, and the board seems to be working normally.
My question is if it safe to use it. Is there any chance of electrical damage or something like that?
Thank you!
P.S. In addition, we are planning to buy a new arduino starter kit. How can we avoid this problem with the new board?

And shield from the usb plug can't be pulled out now? I don't think it's a dealbreaker, maybe just some ultra cheap cable..

Yes, it can't be pulled out. Maybe we could try with pliers, but I think we shouldn't, I believe if we do, we could probably damage the inside of the board. If it is safe to use it this way, we are willing to keep the shield inside the arduino usb port.

at most you can damage usb connector.. Maybe a little squeeze in the middle (just a little in weakest place). Anyway usb connector can be replaced, if you don't destroy something else

@KIIV, was considering making an answer to this, but with your second comment you seem to be covering everything I'd say anyway.  So it makes sense that if it's to be answered, it would be by you rather than me.  I'd tack my own thoughts into a comment if there's anything to add beyond what you say.

Without the center part of the USB plug, it should be possible to make some deformations of that shield without damaging rest of the usb connector and pull it out. Aim for the weakest spot - seam (usually in the middle of bottom).
But even if you damage on board connector, it can be replaced (but it might be better to give it to someone with soldering experience - at least for unsoldering it)
And as noted in comments, even without working usb connector it can be programmed either by connecting USB-TTL serial converter to D0/D1 (but without auto-reset, unless you provide 100nF capacitor between reset and RTS), or it can be programmed by another Arduino as SPI (it needs bit more wires, and by default it doesn't burn bootloader, so if you fix USB, you'll have to burn bootloader).
Easier might be swapping Atmega328p between boards, however it needs some practice, so you won't bend or rip pins)

One thing I had to add is just that in the meantime until fixing it, it's unlikely the USB cable shield sitting in the USB jack will cause any actual electrical problem.  So, it could powered by the barrel jack and programmed by a USB->TTL serial converter via D0 and D1, until it is fixed.


text:
Convert fuel level sender resistance ranges - good Arduino project?
I've noodled around with Arduino a bit, worked some tutorials.  I have an engineering & programming background, but electronics isn't my first language.  So apologies if this is a dumb question.
Here's the problem.  I've swapped a 2007 GM engine into an older Toyota Land Cruiser.  I need to make it compliant with the emissions equipment that was originally on the 2007 vehicle.  Most of that is pretty straight forward - catalytic converters, O2 sensors, charcoal canister, purge & vent solenoid valves, a pressure sensor.  The one bit I haven't figured out yet is fuel level.  The evaporative emissions system requires a fuel level input to the PCM (Powertrain Control Module) so it can figure out when & how to run the fuel system pressure test - the one that turns on your check engine light if your gas cap isn't on tight enough.
One solution would be to put in a GM fuel level sender ... but that involves draining the tank, dropping it, maybe cutting new holes, more wiring, etc.  I'm hoping I can fix this in software :)
The GM fuel level sending unit reads 0 ohms empty and 90 ohms full.  The existing Toyota sending unit should be 110 ohm empty and 3 ohm full.
So ... is it a feasible thing to build an Arduino based project that reads the resistance from the Toyota sender (without interfering with the Toyota gauge) and translates that to the range expected by the GM PCM?
I'm thinking something like this is the core of it: https://www.arduino.cc/en/Tutorial/LibraryExamples/DigitalPotControl  But I don't know what I don't know.
Thanks folks - additional information based on responses:
The Toyota sender is definitely a 12V two terminal unit.  Car electrical systems are nominally 12V, but typically are about 13.3V in operation.
The GM sensor is two terminal also.  According to the wiring diagram, one terminal goes to a low reference pin on the PCM and the other goes to a pin on the PCM labeled fuel level signal.
But it doesn't tell you the voltage they're applying on that pin - could be just 5V, other stuff coming out of the PCM is.  I couldn't find a test procedure either.  I'll pin that connector and see what I can measure next time I'm out there.
The fuel level signal is used for two things in the evaporative emissions (evap) system.

The evap vacuum test can only run when the tank is between approximately 1/3 to 2/3 full.
The vacuum test is calibrated against how full the tank is - lower fuel level means more air space in the tank means the pressure will change more slowly then compared to a fuller tank.

we don't have all the details of how each sensor/device "talks" to the other, but in general, yes, that's likely completely feasible to do with Arduino microcontrollers, and maybe a small amount of support hardware like a DAC (or RC filter) if needed. Break the large problem down to small steps and ask for help if you get stuck on one of them.

The Toyota sensor may be using 12V instead of 5V, which would mean you'd need to use a voltage divider to get it down to the range that the Arduino analog inputs can read.
You will need to find a digital potentiometer that can handle the voltage range that the
GM controller wants to see.  This may be 0-12V, which would be a problem since the AD5206 is only good for 5V.
However, as dandavis implies with his RC filter comment, you may be able to simulate the full 0-12V range with PWM, where the Arduino pin drives a transistor to chop up the 12V, and an RC filter smooths the result for the GM control unit.  That's probably your best approach.
Alternatively, if the GM controller is only looking for a go/no-go level, you can use the
transistor to switch in a simple voltage divider to get the right voltage from 12V.
The sensors are (presumably) just variable resistors (2-terminal) not full 3-terminal potentioneters.  They will most likely be using a series resistor to make a voltage divider, and the control unit (or gage in the Toyota) will reading the resulting voltage. You will want to either find out the value of the series resistor or measure the voltage that the gage sees.  It might already be in the 0-5V range.  The GM control unit may have the series resistor built in (or be using a current source), in which case you should measure the voltage its sensor input sees when you give it the max and min resistance.  This will be good to know when you are trying to drive it with your own circuit,

Thanks - I've added some more info to the original post based on these responses.  There's a decent chance that the GM PCM is only pushing 5V to the sensor, but I haven't been able to find it in the docs so far.  Will try to measure it.


text:
How to flash a NodeMCU (ESP8266) with an external FTDI programmer?
Hi my USB to UART bridge (CP2102) seems to be broken on one of my NodeMCU Dev Boards with ESP8266.
It seems to be just that specific board since all other boards that I have can be flashed without problems.
I have a FTDI Programmer like this one:
FTDI Programmer
Now I would like to flash the Nodemcu using the FTDI programmer but I'm not sure how to wire it up.
I know that those programmers cant power up the ESP8266 by itself thats why I would use a micro USB cable that doesnt have a data wire to power up the nodemcu.
This is how I would wire everything up:

Is this the correct way to wire up the programmer with the nodemcu? I want to be sure that nothing is going to mess up with the nodemcu or the programmer.
NodeMCU       FTDI
GND    ---->  GND
RX     ---->  TX
TX     ---->  RX

Looks fine to me. Just hold the FLASH button and tap RST before you want to program to put it into bootloader mode. You may want to try that with the existing USB connection first before you go through the rigmarole of wiring up an FT232 board.

@Majenko yeah I tried the build in Serial Connection but on this specific Nodemcu I keep getting: ERROR Running command failed: could not open port 'COM3': PermissionError(13, 'Zugriff verweigert', None, 5)

Assuming your FTDI Basic is the 3.3V version, then yeah that will work fine provided you that manually reset the board yourself and enter the boot-loader using the buttons.
If you're independently powering the boards you may want to insert some series resistance in the RX and TX connections in case your signal receiving end is not powered while the sending side is.  In short you don't want the TX signal from one of your devices (boards) trying to power the receiving device (board) through its protection/clamp diodes.
In regard to comment about resistor value:
The value of the resistor depends on what you can get away with in terms of its effect on the signal and how much current is allowed through the clamp diodes on the other board.  A couple of Kbyte is probably sufficient, better than nothing in any case. Use a bit more if you can and still get a reliable signal through.  If you have the boards both powered before you connect them and you're careful about connecting them, then there's no opportunity for that.  It may also just be that they're robust enough that you don't need them at all.  I usually put some in though.  The second reason which I didn't state above is just that it protects you from being outright stupid and accidentally connecting them to the wrong thing; wrong signal, or to VCC or GND on the other side.

which resistors should I use and how exaclty do I wire them up? (The programmer that I have has jumper connectors for 5v and 3.3v)

They're just in series with the signal, which hopefully will be clear in the above.  I'm addressing that only briefly though, otherwise there's more in there about that then just answering the question.

Is it also possible to connect it like this: https://imgur.com/a/Tb7Llow
I'm not sure if the programmer is going to be able to power the nodemcu up but at least then I dont need to mess up with resistors etc. is this possible?

Right, that removes the "independently powering" concern.  Just be careful your code doesn't do something like use pinMode with OUTPUT on the RX pin and you should be fine.

Even on an Arduino UNO, where the serial transceiver and and the microcontroller are powered together, resisters are still in place to protect against accidentally driving serial pins the wrong way; it lets people be a bit more careless.  What you've shown is something I would do, because I know not to try to drive one of the serial pins opposite the FTDI.  If it was something I was putting "into the field" as it were, I'd be more inclined to have them in there, just in case I screw up.

Ok so I tried to flash it while powering the esp with the programmer. Unfortunately Im still not able to flash the esp. I opened the serial monitor on the com port of the programmer to see what boot mode the esp is starting if I press the flash button and then press the reset button this is the output:
ets Jan  8 2013,rst cause:2, boot mode:(1,7)
this should be correct. But its the same case as if I try with the build in USB to UART connection. It cant establish the connection for flashing and just times out. :( I think that I just have a faulty Chip (serial monitor was closed while flash)

Let us continue this discussion in chat.


text:
Fail to burn bootloader into standalone atmega2560
I am making a project where I use standalone atmega2560. I used arduino mega schematic to put all necessary components so atmega2560 would be working. I tried to burn bootloader into it using arduino mega as ISP, but failed. I get this error:
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega2560 -cstk500v1 -PCOM4 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xD9:m -Ulfuse:w:0xFF:m

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM4
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
         AVR Part                      : ATmega2560
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
           flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000 (retrying)

Error while burning bootloader.
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

avrdude done.  Thank you.

I use schematic which I attached.
At first I uploaded arduinoISP example code to my arduino mega and then used it to program several arduino megas to be sure that it is working and then I connected cables to arduino mega ISCP connector which is master and then put them into my PCB board X3 connector which also has SPI connected to it. After trying to burn bootloader I got an error above.
Things I already did:
Made sure that all VCC pins are connected. And AVCC is connected to VCC
Made sure that all GND pins have ground and my PCB has same GND level as arduino mega (programmer)
Made sure that I connected SPI correctly.
Made sure that arduino as ISP is working.
Made sure that VCC level is high (it is about 4.7 V)
I also tried to put external voltage, but it also did not help.
I tried putting capacitor between Reset and GND pins on arduino mega (programmer)
What could go wrong? After all my struggles I came to the conclusion that it is probaby hardware problem, but I cannot find it.
Also I read that atmega2560 by default use 8 MHZ internal clock, can it be a problem?

What exactly is the RESET signal of your target connected to on the "programmer" Arduino?  What pin?

RESET in my arduino mega(programmer) is connected to digital pin 10. I also tried connecting it to digital pin 53 which is slave select, while doing so I change the code. Both methods did not work. In my board RESET is inverted atmega2560 RESET

You know there is widely used ISP header pinout and you are using something completely different?

I use ISP header you just mentioned except RESET pin. I use RESET pin from programmer side as digital pin 10 as mentioned in arduino ISP firmware and website.

Pauliusr, I saw that in your above comment.  Do you understand the significance of what @KIIV has pointed out?  Can you confirm that you know that you're using a non-standard pinout and that you're not miswiring because you think that you have used a standard pinout?

I understand. I can assure that I use standard pinout, because with the same pinout I managed to burn bootloader into another arduino mega

I have not tried standing on my head yet, but every which way I've looked at your ISP header in your schematic, trying to imagine how the footprint could be mated to a symbol in such a way as to make the pins land where the should, has failed to make this look like a normal pinout.  So, I'll have to take your word for it that you've done it with your PCB.  If you're saying you've managed to use arduinoisp.ino on an Arduino Mega to successfully program another Arduino Mega, I'm not too surprised.

Oh sorry. I see what you mean... Yeah I am not using standard header. That is a good point and I should use a standard one, but I am aware of my pinout and I am sure that I connect MISO to MISO, MOSI to MOSI and so on.


text:
SIM A9G: +CME ERROR: 53 failure
I'm using a SIM A9G.  When I send HTTP GET command from the serial monitor, it responds. But, it doesn't work when included in the code.
#include <SoftwareSerial.h>
SoftwareSerial myserial(8, 7); // RX: 8, TX:7

void setup()
{
//  Wire.begin(I2C_SLAVE_ADDRESS);
  Serial.begin(19200);
  myserial.begin(19200);    // 9600, 19200, 38400, 57600, 74880, 115200

//  ET.begin(details(mydata), &Wire);
  Serial.println("JSON Initializing...");
  Serial.println("GPRS Starting..........");

//  myserial.listen();
  myserial.println("AT");
  delay(500);

  myserial.println("AT+CREG=?");     //Check Network regiistration, wait a while
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CCID");  //Specify the connection type
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGDCONT=1,\"IP\",\"web.gprs.mtnnigeria.net\"");//Specify the APN
  delay(2000);
  ShowSerialData();

  delay(2000);
}

void loop()
{
  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGACT=1,1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+HTTPGET=\"https://postman-echo.com/get?foo1=bar1&foo2=bar2\"");
  delay(5000);
  ShowSerialData();

  myserial.println("AT+CCLK?");
  delay(1000);
  ShowSerialData();

  delay(3000);
}

void ShowSerialData()
{
  while (myserial.available() != 0)
  {
    Serial.write(myserial.read());
    //delay(50);
  }
}

The output at the serial monitor is the following:
+CGATT:1

OK
AT+CGACT=1,1

OK
E⸮⸮T⸮OZ⸮y:/⸮͵*⸮⸮⸮m/⸮⸮⸮⸮⸮=bar1&foo2=bar2"

+CME ERROR: 53
failure, pelase check your network or certificate!

AT+CCLK?

+CCLK: "21/02/22,18:19:43+01"

OK

start with the Arduino software serial example sketch

A9G Module also support https request ...Due to some other reason , you are getting that error ... Bcz, i tried same server to get the data , is working fine ..

For me HTTPS working for first 7 or 8 times after that it fails.. @sumit chatterjee for you it works continuously?

You must use this sequence.
AT+CREG=?
AT+CCID
AT+CGATT=1
AT+CGDCONT=1,"IP","ba.amx"
AT+CGACT=1,1

Some explanation as to why might be helpful.

i can confirm that  it works. I tested with my Maduino that didn't connect to server and didn't send HTTP get request.


text:
Connect multiple Arduinos to ESP32's RTC?

Depending on usage frequency, may get the occasional collision where
both test for availability at the same time - if occurring too
frequently, maybe add something simple like one arduino only does time
updates on even seconds, the other on odd seconds.

https://forum.arduino.cc/index.php?topic=64049.0
I need events executed in the multiple receiving Arduino's to occur in sync (simultaneously). Is there a library or something, probably using the ESP32's RTC, to ensure events occur in sync?
Example system:

ESP32 sender/master
Arduino1 receiver controlling LEDs (Christmas lights)
Arduino2 receiver controlling stepper motors (Mary figure)
Arduino3 receiver controlling stepper motors (Joseph figure)

The issue is that they are sent data at different times by the user.
Say, the user selects settings for Mary. That data is sent to the ESP32, and then that data is sent to all the Arduinos, but only "gets into" the MaryArduino.
Then, the user selects settings for the lights. That data is sent to the ESP32, and then data is sent to all the Arduinos, but only "gets into the LightsAruino.
Etc.
However, I need everything to start at the same time.
The data is not simultaneously sent. It is sent one after the other, as slow as the user selects their settings. However, the sequence of events must simultaneously occur.

moving an actuator, turning on a light, running a stepper motor a number of steps, etc.

why do the light and actuator have to be synchronized? ... what is their purpose?

Events need to happen at specific times: Think of a light show synchronized to music.

I said, "events executed in the receiving Arduino_>>'s<<_" but I edited the post with multiple in again (beside already being in the title).

You state: "I need events executed in the multiple receiving Arduino's to occur in sync". What is the tolerance you can allow, this will have a big impact on the plausibility and cost of the design. Is your software designed to be that way and do you know how many clock cycles each remote will do before performing the task, they must be the same to be fully in sync. If not how do you compensate for this difference and how do you detect an error.

light synchronized to music is not an example of simultaneous events, as far as the microcontroller is concerned  ... it only has to look synchronized to a human ... a microcontroller can go on vacation between two events and the two events would still look simultaneous to a human

Lights synchronized to music IS an example of simultaneous events since they are both done by different Arduino's (as that's how it's meaningfully related to the question asked).

@Gil No software has been designed. That's why I'm looking into this question. The idea is to use the ESP32's RTC connected to multiple receiving Arduinos. The ESP is the sender. Say three are connected. All three would be going off the ESP32's RTC.

it is unckear what the overall system consists of .... perhaps the simplest solution is to have a hardware clock signal that connects all of the arduinos

So gather the data from the sender, and hold until a digital signal is sent? E.g., lights get song, figure1 gets sequence of movements, then figure2 gets sequence of movements. Once the last event happens, wait part of a second and send a digital HIGH signal. And just have a simple if-statement waiting for that signal?

use serial, the ESP32 has 3 of them, and capability to do many more. the AVRs do stuff when told to over serial. the ESP32 tells them what to do over serial. Even though on a microscopic level the messages will be staggered by microseconds, it won't make a hill of beans difference to a light show, or even most scientific experiments.

I'm using one serial connection to send the commands to all the Arduinos (10-30). @dandavis Are you suggesting that same serial connection be used OR 10-30 additional serial out? The latter isn't really possible as you know.

@adamaero You can connect serial in parallel, ironically. if your high-level protocol allows all nodes to get the same broadcast, typically by each having an ID/tag it's "interested" in ala wifi/i2c, there's no real limit. If each line has to transmit different messages, then you can still easily do a dozen or two with an ESP32, since you only need TXs and it has a whole dang bunch of pins ;)

Yes, I have each Arduino addressed already: if(charArr1[0] == motionHead) strcpy(str2, charArr1); They are all being sent the same data, but only each one is receiving their specific data.

then just wire all the slave RXs together to the master's TX, and then send away. With a message format like "MARY=1;RED=1", at 57k baud, mary and the red light will turn on at the same time (fraction of a ms), even to a high-speed camera, much less a human.

Let us continue this discussion in chat.

Try this link for a paper by Autosar Specification of Time Synchronization over CAN: https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_TimeSyncOverCAN.pdf It has a lot of good information.

Give the master a single signal wire that is connected to all of the slaves and that signal LOW while the master sends commands to each slave. Let each of the slave Arduinos simply store its message but not act on it while the signal wire is LOW.
When the slaves are supposed to start, raise the signal level to HIGH. Each slave Arduino now executes whatever command it had been sent. The RTC now only needs to be connected to the Master, which controls all of the timing.


text:
Input Capture Mode PPM signal
Greetings to all members of the Forum. I would like to express my deepest gratitude, with respect to the title of this post.
The last week I am trying to capture and decode a PPM Signal from an RC transmitter. Although I have seen many different approaches and codes online, using methods like Input Capture Mode and Pin Change Interrupts I would like to seek some help on my approach.
Most of the codes I have found online present glitches and instabilities while trying to read the time between the rising pulses.
I have tried to read and understand how to set up the Input Capture registers on the Atmega 32u4 chip, aka Arduino Pro Micro / Lepnardo, but I cannot find a proper way of defining the registers as well as the ISR (_vec) function.
In the next few lines I will try to explain the code I have written so far, but I will need some help with respect to the initialization of registers.
Please bare with me, as any help will be much appreciated. Without further ado, let me introduce you to the following lines.

#define STICK_CENTER 1500
#define STICK_HALFWAY 500
#define THRESHOLD 15

#define MIN_PULSE_WIDTH (STICK_CENTER - STICK_HALFWAY - 15)
#define MAX_PULSE_WIDTH (STICK_CENTER + STICK_HALFWAY + 15)

#define RC_CHANNELS_COUNT 8

#define PPM_CAPTURE_PIN 4
#define NEWFRAME_PULSE_WIDTH 2000
#define TIMER_COUNT_DIVIDER 2

void rc_setup_ppm() {
  setupPins();
  initTimer();
}

void setupPins(void) {
  // Set up the Input Capture pin
  pinMode(PPM_CAPTURE_PIN, INPUT);
  digitalWrite(PPM_CAPTURE_PIN, 1); // enable the pullup
}

void initTimer(void) {
  cli();

  TIFR = (1 << ICF1); //Clear any Interrupt flags
  PRR |= (0 << PRTIM1); //Enable Timer1
  TCCR1A = 0; //Clear TCCR1A
  TCCR1B = 0; //Clear TCCR1B
  TCCR1C = 0; //Clear TCCR1C
  TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
  TIMSK1 |= (1 << ICIE1); //Enable input capture
  TIFR1 = (1 << ICF1); //Clear interrupt flag

 sei();
}

uint16_t adjust(uint16_t diff, uint8_t chan) {

  return diff / TIMER_COUNT_DIVIDER;
}

ISR(TIMER1_CAPT_vect) {
  union twoBytes {
    uint16_t word;
    uint8_t  byte[2];
  } timeValue;

  uint16_t now, diff;
  static uint16_t last = 0;
  static uint8_t chan = 0;

  timeValue.byte[0] = ICR1L;    // grab captured timer value (low byte)
  timeValue.byte[1] = ICR1H;    // grab captured timer value (high byte)

  now = timeValue.word;
  diff = now - last;
  last = now;

  //all numbers are microseconds multiplied by TIMER_COUNT_DIVIDER (as prescaler is set to 1/8 of 16 MHz)
  if (diff > (NEWFRAME_PULSE_WIDTH * TIMER_COUNT_DIVIDER)) {
    chan = 0;  // new data frame detected, start again
  }
  else {
    if (diff > (MIN_PULSE_WIDTH * TIMER_COUNT_DIVIDER - THRESHOLD)
        && diff < (MAX_PULSE_WIDTH * TIMER_COUNT_DIVIDER + THRESHOLD)
        && chan < RC_CHANNELS_COUNT)
    {
      rc_values[chan] = adjust(diff, chan); //store detected value
    }
    chan++; //no value detected within expected range, move to next channel
  }
}

Given the above I would like to help setting the initialization routine of the registers. Some information about my signal:
PPM includes 8 different channels as a summed signal. In total 9 pulses while each one, has a time duration from 998 - 2012 microsecs.
The time frame of each pulse is easy to be changed though the transmitter settings. Also the total period of the frame can be changed. By the first I mean the HIGH time of each pulse, and by the second I mean the total frame period after the 8 channels have been scanned. Given these, the time periods are 26.5 mills and 350 microsecs.
Enough with these. Going back to the actual code you will see the cli(); and sei(); functions. Do I really have to set these during that part of the code?
Also do I need to reset or delete any active flags? Should I include any flags (e.g. Overflow flag after the counter has reached its peack value)
At this point I would also like to mention that I am using a prescaler of 1/8, which results to a tick period of apx. 0.5 microsecs.
Also, I am capturing only the rising part of the pulses. And I am using an Input canceler, but given the datasheet specifications I have seen that the cancel frame is 4 periods long. Is there any possible way to use a low latency filtering scheme?
Please take some time to read this post, as I am confident enough that any responses will help others too clarify these topics.
I know that I have included many different aspects and I feel sorry for this.
Many thanks,
Koutsoukos Theodosios

I feel like you're about to pull a rabbit out of a hat or challenge us to a duel or something.  In all seriousness, you'll probably have better luck if you cut this down.

Sorry for the contents of my post. I would like to seek advices only to the Initialization of the input capture mode. Only the registers and how to  use these.

I could probably write something about how to setup input capture.  But in your question you mention that you're trying to do this with 8 different signals.  The 32u4 only has 2 input capture pins.  That would seem to be something of a problem for you, if I understand correctly.

Dear timemage, thank you for your reply. It was something I wrote wrong, so please forgive me. I meant that the ppm signal contains 8 different signals, (9 pulses in total).

If "after the 8 channels have been scanned" means after "after 8 pulses..." you can edit your question  to say that.  Clarifications to questions asked here normally supposed to edited into the question.

Many thanks once again, I have change it and included what really happens.

Do I really have to set these during that part of the code?

No, you don't. I would, however, change the order of the last
initializations:

Update TIFR1 right before TIMSK1 in order to avoid an interrupt to
be triggered immediately.

Set TCCR1B last in order for the timer to start only when it has
been fully configured.

Also do I need to reset or delete any active flags?

AFAIK the Arduino core does not use the Timer 1 interrupts. You can take
control of all the bits in the registers (e.g. TIMSK1 = (1 << ICIE1);)
instead of only some selected bits. It shouldn't make a difference
though.

Should I include any flags (e.g. Overflow flag after the counter has
reached its peak value)

Do not worry about overflows. The computation diff = now - last is
done modulo 216 and, owing to the rules of modular
arithmetics, gives the correct result even across an overflow.

And I am using an Input canceler, but given the datasheet
specifications I have seen that the cancel frame is 4 periods long.

This creates a delay of “four system clock cycles”, or 0.25 µs. Do
you really care about such a small latency? Please note that, since all
edges suffer the same latency, it doesn't affect the calculated
differences.
Now, if I may, a couple of comments about your code:
  pinMode(PPM_CAPTURE_PIN, INPUT);
  digitalWrite(PPM_CAPTURE_PIN, 1); // enable the pullup

This can be simplified an made more explicit:
  pinMode(PPM_CAPTURE_PIN, INPUT_PULLUP);

Then,
  union twoBytes {
    uint16_t word;
    uint8_t  byte[2];
  } timeValue;
  timeValue.byte[0] = ICR1L;    // grab captured timer value (low byte)
  timeValue.byte[1] = ICR1H;    // grab captured timer value (high byte)
  now = timeValue.word;

This used to be the way to read 16-bit registers a long time ago. Since
many years now, the C compiler knows how to do it, you just have to
issue:
  now = ICR1;

This contains most of what I was writing, so I'm just going to vote this up.

PRR |= (0 << PRTIM1); -> PRR0 &=  ~(1 << PRTIM1);

TCCR1C = 0; does nothing useful.

Dear Edgar, timemage, many thanks for your replies. Especially to the the one from Edger, which included everything I was asking for. Just amazed by the simplicity and the way you did transmit all the information. Cheers!


text:
Arduino MKR GMS alternative
I’m starting on a project about monitoring the soil in the agriculture field and also to visualise the data remotely. The aim of this project is collect the atmospheric data as well as the soil related parameters and then send them to cloud where they’ll be presented on the dashboard. I decide to use Arduino as my development board and Arduino MKR GMS 1400 would be perfect for this project. However this board is quite expensive. So just wondering that are there any alternative I can use for this project
Thank you

sounds like any microcontroller would be sufficient ... not really an Arduino question

There are multiple options for this project as you just want to send/ upload data on the cloud server rather than using Arduino MKR 1400 you can use any of the following.

Arduino UNO with GSM module: As per your requirement you can use Arduino UNO to read the data from the sensor and the GSM module will be used to upload the same on the cloud server. There are various GSM modules available in the market which are cheap also and good. You can also use SIM800 one of the GSM module.

Other GSM modules which you could use can be,
SIM900, Quectel EC-20, Quectel M95. You can also visit SIMCONN website where you can find multiple GSM module options.

You can also use ESP8266 or ESP32 which are Wi-Fi modules but in this case you will require a internet/ Wi-Fi connection near the controller. ESP8266/ ESP32 will read data from the sensors and can also upload the same to the cloud servers. But as you said you are using them to monitor agriculture field it won't be possible to have a Wi-Fi which will cover such long range.

One of the possible solutions to the problem is to use RF-link to transmit data and collect it at a base-station and from the base station you can upload/ send them to the server.

You can also make use of the LoRa Network to communicate along the fields and then receive data from the whole field at a base station and then upload them to the server. But this could be a more expensive solution.

Instead of using the LoRa network you also could use 433mhz modules with an antenna to extend range communicating with a base station, but I'm not sure if the Antenna is helping enough and the range might not be covered though.


text:
Collecting data from a timer interrupt and storing it into an array
My question is: how can I use an ISR and store the data I get from my analog inputs into an array for easier data analysis.
More specifically, I want to collect my data using an ISR function (internal timer interrupt), then store the collected data into an array. This way I can analyze the data more easily.
I have posted the code below. I have posted code showing how I implemented my ISR without storing the data into an array. I was wondering I anyone could help me out with this (how to store that data into an array). Thank you.
const int A0_pin = PC0;
const int A1_pin = PC1;

const uint16_t t1_load = 0;
const uint16_t t1_comp = 3173;

float count = 0;
float num = 0;

void setup() {

  //Set A0 and A1 pins as inputs
  DDRC &= ~(1 << A0_pin);
  DDRC &= ~(1 << A1_pin);

  //Reset Timer1 Control Reg A
  TCCR1A = 0;

  //Set CTC mode
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

  //Set to prescaler of 256
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B &= ~(1 << CS10);

  //Reset Timer1 and set compare value
  TCNT1 = t1_load;
  OCR1A = t1_comp;

  //Enable Timer1 compare interrupt
  TIMSK1 = (1 << OCIE1A);

  //Enable global interrupt
  sei();

  Serial.begin(9600);
  Serial.println("CLEARDATA"); //clears up any data left from previous projects
  Serial.println("LABEL,TIME,TIMER,AVG,GAUGE0, GUAGE1"); //always write LABEL, so excel knows the next things will be the names of the columns
  Serial.println("RESETTIMER"); //resets timer to 0
}

void loop() {
}

ISR(TIMER1_COMPA_vect) {
  TCNT1 = t1_load;
  float Gauge0 = analogRead(A0_pin);
  float Gauge1 = analogRead(A1_pin); //44

  //conversion of read data, to voltage range (0-100 percentVolts)
  float gauge0 = Gauge0 * (100.0 / 1023.0);
  float gauge1 = Gauge1 * (100.0 / 1023.0);
  float add = gauge0 + gauge1;
  float AVG = ((gauge0 + gauge1) / 2);

  Serial.print("DATA,TIME,TIMER,");
  Serial.print(add);
  Serial.print(",");
  Serial.print(gauge0);
  Serial.print(",");
  Serial.println(gauge1);
}

In the code, I want to store the gauge1 and the gauge0 values into an array essentially.

How many interrupts/second do you expect? Using Serial.print() in the interrupt routine is introducing a significant performance penalty, especially since you've set the communication speed to only 9600 baud.

Storing the data into arrays is not an end in itself. The question is:
what do you want to do with these arrays? The way to proceed depends on
that purpose.
If you want the data acquisition (analogRead()) and the processing
(computation and printing) to proceed in parallel, then you will need
the arrays for buffering the data between those two processes. As
mentioned by Michel Keijzers in his answer, you will have to research
the concept of ring buffer.
There is a ring buffer implementation in the Arduino core you can use as
inspiration: when reading data from the Serial port, the incoming bytes
are received by an ISR and stored in a ring buffer. The
Serial.read() method can then be used to retrieve these bytes
and process them outside the interrupt context.
Another option is to alternate between an acquisition phase and a
processing phase. This can be an interesting approach if the acquisition
rate is too fast for the processing to be performed in real time. In
this case, you do not need a ring buffer. Instead, you have the ISR fill
the arrays and, when they are full, the main program can take on and
start the processing. For coordinating these jobs, you just need a
boolean to keep track of whether you are performing the acquisition
phase or the processing phase. Note that, since accessing a boolean is
an atomic operation, you do not need to disable interrupts for this.
Here is an example implementation of this strategy. The variable
sampling_done is used to coordinate the two processes:
const size_t sample_count = 256;

volatile int gauge0[sample_count];
volatile int gauge1[sample_count];
volatile bool sampling_done = false;

ISR(TIMER1_COMPA_vect) {
    if (sampling_done) return;  // nothing to do

    static size_t sample_idx = 0;
    gauge0[sample_idx] = analogRead(A0);
    gauge1[sample_idx] = analogRead(A1);
    if (++sample_idx >= sample_count) {
        sample_idx = 0;  // prepare for next round
        sampling_done = true;
    }
}

void process_samples(int Gauge0, int Gauge1) {
    // Whatever needs to be done with the samples:
    // computation, printing...
}

void loop() {
    if (sampling_done) {
        for (size_t i = 0; i < sample_count; i++) {
            process_samples(gauge0[i], gauge1[i]);
        }
        sampling_done = false;  // start next sampling round
    }
}

Now some random remarks:

There is no need to sei() in setup(): interrupts have already been
enabled by the Arduino core initialization.

Do not reset TCNT1 within the ISR: this is handled automatically by
the CTC mode. If you do this in software, you risk missing timer
ticks.

Do not store the readings in float variables: they take twice the
memory of an int and all operations on floats are incredibly slow
compared to the equivalent operations on ints.

The scale factor for converting the readings to percent scale is
100.0/1024: the maximum possible analog reading (1023) is one ADC
step below the reference voltage: see the datasheet.

You should remove unused variables as soon as they become unused
(count, num, AVG). Once you do that you should notice you do not
need floats at all.

Thank you for the suggestions. A few side notes: what do you mean by  process_samples(gauge0[i], gauge1[i]);

@DemaGovalla: I mean “do whatever you want with the samples”. See amended answer.

You can create two arrays, e.g.:
#define MAX_LENGTH 20

volatile float _gauge0[MAX_LENGTH];
volatile float _gauge1[MAX_LENGTH];

volatile int _filled = 0;

The _filled value shows that _gauge0 is filled from 0 upto (excluding) _filled.
So when adding two values you use:
_gauge0[_filled] = some value;
_gauge1[_filled] = some_other_value;
_filled++;

After processing, you reset _filled to 0 to refill both arrays again.
Because the Arduino has a limited amount of SRAM it's best to use a fixed array size (20 in this case). You have to make it volatile as it's used from within the ISR.
I'm not sure what you want to do with the data. If you want to gather like 20 (or a fixed amount of values), you can use the above.
If you need a continuous amount of memory and get the last x results, you can better use a so-called ring buffer (search for this, there are many articles about it).
Note that because of the limited amount of SRAM, it might be best not to store calculated values (like average and sum), unless you need the highest performance. This is a tradeoff which I cannot make as I don't know your requirements.
While processing, you use noInterrupts() before and interrupts after the processing of the data, otherwise interrupts will continue during processing. Make sure the handling of the processing takes as less time as possible as you might miss interrupts. Preferably only do the calculations and switch on interrupts before sending results via serial for example.

You would likely need to read _filled when processing the data, so it too should be volatile.

@EdgarBonet Good point, I updated my answer.

My DaquinOscope https://www.daqarta.com/dw_rroo.htm  uses the open-source DaqPort sketch https://www.daqarta.com/dw_rraa.htm to sample in batches, then transfer the data to the host in one high-speed blast.  It takes 1024 total samples, which in your case of 2 channels would be 512 per channel. It stores only the raw data, unscaled... the host is the place for that. The host processes and displays the results in real time. Since this uses a UNO with only 2K RAM, tricky array storage was required to fit in 1024 samples.  In 8-bit mode this is just a 1024-byte array, but for 10-bit it uses a supplemental array of 256 bytes.  On each sample the low byte is stored in the 1024-byte array, and the upper 2 bits are shifted into a 4-sample byte of the 256-byte array.  Feel free to download and use Daqarta for this... no charge for Arduino use. You may want to do this just to work out other issues even if you plan to later use your own host software.  Or you can use Daqarta macros to do whatever you ultimately want.


text:
micros() resolution for Portenta H7
Is there any way to know the resolution of micros() for the Arduino Portenta H7. I have checked for other boards e.g. Nano which is mentioned as 4 uS. However, I couldn't find one for Portenta H7.
Is there any way to measure or look for that

Maybe grab the value in a tight loop and compute the shortest difference you find?

@PMF: That would only give an upper boundary: the resolution could conceivably be smaller than the time taken by a loop iteration.

I agree, but it would be a first hint.

A Protenta is completely different from a standard AVR Arduino. It is built with a M7/M4 dual core ARM mcu running on 480/240 MHz. There is also an OS installed on the board (mbed OS). The sketches run on top of this OS. I don't know the actuall status but ~2015 (?)  I followed a discussion about using a 'millis()' resolution of 50µs Arduino_mbed core. Unbelievable I know, but the reason was: The OS runs tasks and a timer irq with a call frequency  of a MHz would slow down the scheduler and the tasks.

So the discussion was seriously about a 50µs resolution that leads to 20kHz Timer IRQs. I'm not sure if this is still the truth. But if they still use a 50µs resolution you could follow the idea of @PMF and see if the difference between two micros() calls is dividable by 50 or 30 or whatever.

I did some measurements today. I used digital pins of the board to ON and OFF during each analogRead call for ADC.  These digital pins are then connected to the Oscilloscope.
Also, I used the micro() before and after the analogRead in my sketch to measure the time from the board. I obtained approximately 4uS time which it takes to execute one analogRead(), using an Oscilloscope.  However, the micros() function of the board couldn't give me that value. So it was showing the same time before and after the analogRead call.

Then, I called analogRead multiple times to increase the execution time and found that the maximum resolution I could obtain using micros() was around 32uS. This is inferior to the ordinary Arduino board even.

The question was cross posted to Arduino forum where user sbhklr asserted that the resolution was 1uS without providing any reasoning or references. https://forum.arduino.cc/t/micros-resolution-for-arduino-portenta-h7/697386

The question was cross posted to Arduino for STM32 forum, with some success. https://www.stm32duino.com/viewtopic.php?t=934  User edogaldo quoted Arduino doco in support of the 1uS answer. https://www.arduino.cc/reference/en/language/functions/time/micros/

The micros() language reference states that, "[The micros() function] returns the number of microseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 70 minutes. On the boards from the Arduino Portenta family this function has a resolution of one microsecond on all cores. On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.
It seems likely that the doco was updated some time after the OP posted the question.


text:
Save highlighted text as int variable
I build a macro keyboard and one thing I do alot is add a set amount to numbers mostly in 3d modeling programs. I add and remove 0.25 and 0.125 all the time. I want to make a macro that copies selected text, adds or subtracts a value then pastes it back.
I known the simple copy and paste commands but how do I get my arduino program to grab that copied value?
Can this even be done?

What keys does it have, what is the current sketch (or related parts),  how is text selected, can it handle multiple keys simultaneously? I miss the actual requirements and current code you have.

My keyboard has 9 keys and mutable modes I can put it in for different programs. How I want it to work is I select text on my screen its normal an z x or y I need to move by a set amount. I push one key on the arduino macro keyboard and it copies that text imports it as an int adds or subtracts the needed amount then pastes the edited value back.

You can't. A keyboard is a one-way device.

"Can this even be done?" Not without help from the PC side.  It's not like the clipboard stored in the keyboard.  And there are no scan/codes or USB-HID messages that will cause the host to send a copy of the clipboard to the device.

You have to write an application for your PC that

reads a number from the clipboard
adds some constant
puts the result back in the clipboard
quits

Then you have to configure you desktop environment in order to have this
application launched from a keyboard shortcut.
Once you have done that, you can do the whole operation from a regular
keyboard: Ctrl-C + Launcher shortcut + Ctrl-V.
If you can do it from a regular keyboard, you can do it from the Arduino
emulating a regular keyboard.
Edit: The way you do the first two steps is very dependent on the OS
running on your PC. On Linux, for example, the mentioned “application”
can be a minimal shell script:
#!/bin/bash

x=$(xclip -o -selection clipboard)
xclip -i -selection clipboard <<< $(bc <<< "$x + 0.25")

These steps are, however, outside the scope of this site.

I guess I will see if I can make a blender plugin that does what I want and just have it bind to a key combo I can have they macro keyboard do

Well, as long as we're just doing tech support: For what it's worth, in Blender you can click into the number, hit END and type +0.25 and ENTER or whatever other expression you want to do, * pi or / 2 etc.


text:
Simple ESP to ESP reading blink program not reading input voltage
One ESP32's 3v3 is connected to GPIO 26 of another ESP32.
The program is uploaded. The built-in LED lights for two seconds as expected. Then, it turns off. No matter what GPIO pin the 3v3 is connected to (besides 2), the LED remains off.
/*
 * ON Board LED GPIO 2
 */

#define LED 2
#define inPin 26

void setup()
{
  Serial.begin(9600);
  // Pins 34, 35, 36, 39 are input only
  pinMode(LED, OUTPUT);

  // Sanity check LED works
  digitalWrite(LED, HIGH);
  delay(2000);
}

void loop()
{
  Serial.println(digitalRead(inPin));
  digitalWrite(LED, digitalRead(inPin));
}

Any reason this is happening? Grounds are connected. Simply trying to turn LED on/off if external voltage occurs at any GPIO pin (e.g., 26).

are you saying that you are attempting to power one ESP32 from the GPIO pin of another ESP32?

Have you connected the GND pins of the two ESP?

@jsotola .....no

@PeterPaulKiefer yes

you have a serial.println() statement in your code ... please add the resuling printout to your post

"0" ad infinitum

Arduino GPIO automatically set as inputs, so I assumed the same for ESP32. Once the pinMode of the input pin was set, it worked:
#define LED 2 // ON Board LED GPIO 2
#define inPin 26

void setup()
{
  Serial.begin(9600);
  // Pins 34, 35, 36, 39 are input only
  pinMode(LED, OUTPUT);
  pinMode(inPin, INPUT); // <----------
}

void loop()
{
  Serial.println(digitalRead(inPin));
  digitalWrite(LED, digitalRead(inPin));
}


text:
Linking the Arduino Bootloader In Atmel Studio
I have been trying to get the Arduino bootloader to compile into my firmware binary in Atmel Studio. I got the bootloader project to link and compile. I use ArduinoCore and the bootloader as a dependencies to my main code. The dependency tree looks like:

ArduinoCore
bootloader
Main firmware

The Bootloader
It took me a bit to get the bootloader to accept the rest of ArduinoCore as a dependency but it compiles into a static library. I use the bootloader linker to specify the memory location of the bootloader binary. It should start at 0x0 and provide a jump to the main firmware, located at 0x2000.
Bootloader linker flags:
-Tbootloader_samd21x18.ld -Wl

And here are the contents of the linker script:
  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /* First 8KB used by bootloader */
  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */

This is based off of the .cProj file that comes with the linker. It is compiled as a static library so I can include it into my final binary.
Main Firmware
My code has both the ArduinoCore and the bootloader static libraries as dependencies:
libm
libArduinoCore
libbootloader

And I am using these linker flags:
-Tflash_with_bootloader.ld -Wl,--cref -Os -Wl,--check-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align

The contents of this linker script are moved out by 8KB in order to accommodate the bootloader at the start of the binary:
    FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000  /* First 8KB used by bootloader */
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000

And yet, my entry point does not appear to ever hit the bootloader. It jumps straight to "main.cpp" from ArduinoCore. The firmware runs as expected, but the bootloader does not appear to have been included.
Is this some kind of dependency issue? Am I misusing the linkers?
Any help with getting this to compile under a single binary would be very much appreciated. Thank you very much!

it is not really an Arduino question

" .cProj file that comes with the linker." I'm guessing you meant "with the bootloader."  Is the goal just to wind up with a single binary that has both the sketch code and bootloader in it, because the IDE and arduino-cli do that.  Or do you really really want to use ATMEL Studio for some reason?

My whole project is in Atmel Studio. Doing it in Arduino IDE is not possible at this point, especially after modifying some of the core files. I think I have solved it for now using srec_cat.

This isn't exactly 100% the answer I was looking for, because I still want to know how I can use a static library build, as I mention in my post, and compile everything as a single binary. This method is essentially gluing two binaries together.
I found this great and informative post over here:
https://www.avrfreaks.net/forum/can-you-combine-appbootloader-using-as7
It uses srec_cat to concatenate two binaries after building them:
https://www.keil.com/support/docs/2666.htm
I use the offset specified from the '.ld' file using
srec_cat <firmware1.bin> -Binary <firmware2.bin> -Binary -offset 0x2000 -o <firmwareOut.bin>
As the post suggests, I set this up as a post-build event and set my build dependencies accordingly so that a full clean and make will produce a consolidated binary including the bootloader.
If anyone tries this, make sure you only use the non-bootloader binary generated by your main project build. The bootloader places new firmware at location 0x2000 and your firmware will break if it finds a bootloader at the location where the firmware is supposed to be. When uploading firmware to the bootloader, it does not overwrite the bootloader.


text:
How to exit out of a timer interrupt (ISR(TIMER1_COMPA_vect))
I have a code here where I collect an array of data and do some data analysis with the data. The only thing I'm struggle with is how to exit the ISR after I am done running my code. I am using a pre-scalar of 256 and running the ISR once (1Hz)
const signed int numReadings = 21;
volatile int gauge0[numReadings];
volatile int gauge1[numReadings];
volatile int add[numReadings];
volatile int deltaGAUGE;
volatile int slopeADD;
volatile int mean;

const int A0_pin = PC0;
const int A1_pin = PC1;

const uint16_t t1_load = 0;
const uint16_t t1_comp = 62500;

void setup() {

  //Set A0 and A1 pins as inputs
  DDRC &= ~(1 << A0_pin);
  DDRC &= ~(1 << A1_pin);

  //Reset Timer1 Control Reg A
  TCCR1A = 0;

  //Set CTC mode
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

  //Set to prescaler of 1024
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B &= ~(1 << CS10);

  //Reset Timer1 and set compare value
  TCNT1 = t1_load;
  OCR1A = t1_comp;

  //Enable Timer1 compare interrupt
  TIMSK1 = (1 << OCIE1A);

  //Enable global interrupt
  sei();

       Serial.begin(9600);
       Serial.println(" ");
       Serial.println("START");
        Serial.println(" ");

}

ISR(TIMER1_COMPA_vect){

       Serial.println(" ");
        for (unsigned int i=0; i<numReadings; i++)
            {
                        gauge0[i] = (analogRead(A0_pin))*(100.00/1024.0);
                        gauge1[i] = (analogRead(A1_pin))*(100.00/1024.0);
                        add[i] = ((gauge0[i]+gauge1[i]));

                        deltaGAUGE = abs(add[20] - add[0]);
                        slopeADD = abs((add[20]-add[0])/(20-0));
                        mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+

                     add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;

                        if(i == 20)
                {
                      Serial.print("This of the delta AVG reading: ");
                      Serial.println(deltaGAUGE);
                      Serial.println(" ");
                      Serial.print("This of the slope reading: ");
                      Serial.println(slopeADD);
                      Serial.println(" ");
                      Serial.print("This of the mean reading: ");
                      Serial.println(mean);
                      Serial.println(" ");
                      Serial.println("END");
              }

                        delay(50); //wait .05 sec

          }

}

void loop()
{

}

When I run the circuit, the interrupt keep executing every seconds for an infinite amount of time, while I just want it to run once and exit.
I have tried the exit(0) command but I get an output that looks like this
START

This of the delta AVG reading: 0

This of t

As you can see, The program does not execute completely. Anyone have any idea how I can fix this, or anyhow I can better my code? thank you.

take all the code in ISR and move it into an if block inside loop() ... set a flag inside the ISR ... set the if block to execute when the flag is set

ISRs are time critical and should finish as fast  as possible. Yours is taking much too long. Look very critically at what MUST be done when an interrupt occurs and move all other code out of the ISR, especially all of the time consuming Serial.print() and the delay(). Let the main program handle the calculations and the output. The ISR only needs to do the measurements.

Forget about interrupts and read Blink Without Delay.

@StarCat it's even worse. delay and to some extent Serial.print require interrupts to work, but all interrupts are disabled while running your ISR code. So the code will just hang.

Why are you using a hardware timer for a long interval like 1 second? Why don't you just use millis() (or micros(), if you need more precision) to time the measurements? That would be way easier

At least part of the issue is that you never turn the interrupt you enabled back off. Of course it will run again the next time that condition/timer overflow occurs.

As some of the comments have suggested, I would either get rid of the ISR or reduce the size significantly. When using ISRs, it is recommended that you keep the code as small as possible. Use it to set variables, for example
//these two variables are global
ISR(TIMER1_COMPA_vect){
    someValue = true;
    numberOfValues++;
}

you should also never use any Serial functions inside an ISR as these use interrupts themselves which can cause all kinds of problems
After using the ISR to update global variables, you can then use if() or while() statements within the loop() function to execute your serial print functions and such
P.S. on a side note, I would recommend changing your code where you calculated mean from
    mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+
add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;

to
for(uint8_t i = 1;i<=20;i++){
    mean += add[i];
}
mean /= 20;

Use cli(); to completely disable interrupt. Then use sei(); to re-enable the interrupt if you need it later.


text:
Checking what ESP8266 module that is in use
I have this script where I have connected an ESP-01 to an SSD1306 OLED screen. However, the script I'm using needs adaption for ESP-01 as this module requires the I2C pins to be defined.
So basically I need to add a line that says Wire.begin(2, 0); so make the screen work with the ESP-01.
Whoever, I would love to have a check that is wrapped in a #ifdef so the code will work out of the box with multiple ESP modules without changing the source code.
Is there some way I can check if the module in use is an ESP-01?

you can check with ifdef which board is selected in Tools menu

@Juraj As programming the ESP01 requires me to use the Generic 8266 Module option, I guess it's not possible then?

try the ARDUINO_BOARD macro, which is different for wemos and nodemcu and esp01, not sure about others...


text:
Explanation of code found online
i found following code online, to read the value of a touch sensor... i am having difficulties understanding how the 2 second timeout on the marked line works..
 if ((touch_sensor_value (TOUCH_timeSeconds * 1000))) {
touch_sensor_value is the value read from the touch input.. and the rest?? i dont see any comparison with anything in the parenthesis, i cant figure out how this if condition is working...
#define TOUCH_timeSeconds 2
uint64_t now = millis();
unsigned long lastTrigger_TOUCH = 0;
bool startTimer_TOUCH = false;
bool buttonIsPressed = false;

int touch_sensor_value = 0;
//Mux control pins
int s0 = 26;
int s1 = 27;
int s2 = 14;
int s3 = 12;
//State array
int currentState ;
//Mux in “SIG” pin
int SIG_pin = 33; //is touch sensor
void setup()
{
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
pinMode(s3, OUTPUT);

digitalWrite(s0, LOW);
digitalWrite(s1, LOW);
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);

Serial.begin(115200);
Serial.println(“Multiplexing 1 Touch sensor ESP32 using CD7HC4067 MUX”);

}

void loop() {

for (int i = 0; i < 16; i ++) {
currentState = readMux(i);
touch_sensor_value = touchRead(T9);

if ((touch_sensor_value (TOUCH_timeSeconds * 1000))) {    <-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Serial.println(“2 Second LOCK OUT: No rapidly repeating readings”);
buttonIsPressed = false;
startTimer_TOUCH = false;
return;
}

//

}

// delay(1000);
}

int readMux(int channel) {
int controlPin[] = {s0, s1, s2, s3};

int muxChannel[16][4] = {
{0, 0, 0, 0}, //channel 0
{1, 0, 0, 0}, //channel 1
{0, 1, 0, 0}, //channel 2
{1, 1, 0, 0}, //channel 3
{0, 0, 1, 0}, //channel 4
{1, 0, 1, 0}, //channel 5
{0, 1, 1, 0}, //channel 6
{1, 1, 1, 0}, //channel 7
{0, 0, 0, 1}, //channel 8
{1, 0, 0, 1}, //channel 9
{0, 1, 0, 1}, //channel 10
{1, 1, 0, 1}, //channel 11
{0, 0, 1, 1}, //channel 12
{1, 0, 1, 1}, //channel 13
{0, 1, 1, 1}, //channel 14
{1, 1, 1, 1} //channel 15
};

//loop through the 4 sig
for (int i = 0; i < 4; i ++) {
digitalWrite(controlPin[i], muxChannel[channel][i]);
}

//read the value at the SIG pin
int val = analogRead(SIG_pin);

//return the value
return val;
}

Does that code even compile? there is no operator between touch_sensor_value and (TOUCH_timeSeconds * 1000). Thus this would be handles as a function call, but touch_sensor_value is not a function, but a variable.

Link to the code?

@EdgarBonet https://microcontrollerslab.com/esp32-touch-sensor-button-example/ it's down below in the comments...

@chrisl thats actually what i am wondering too...

The comment form of a blog is not an appropriate place to publish source
code, as the content-management system (Wordpress here) quite often does
some destructive transformations. For example, here:
Serial.println(“2 Second LOCK OUT: No rapidly repeating readings”);

Wordpress tried to be “helpful” and replaced the ASCII quotes (") with
typographic quotes (“ and ”), which makes the line non-compilable.
As for the line you are asking about:
if ((touch_sensor_value  (TOUCH_timeSeconds * 1000)))

it is likely missing a less-than sign (<), as those are often stripped
from user-generated content for security reasons. I don't know why some
of those signs went through the filter, maybe it has something to do
with the white space surrounding them, but this is pure guess.
Given that the code has been destructively mangled, your options are
either to guess from the context, or post a comment asking for
clarification.

Thank you.. a < sign wouldnt make much sense, since touch_sensor_value holds the value of the sensor itself, and the part in parentehsis is a time...  there must be more missing... I'll try to figure it out.. thank you


text:
Adafruit CCS811 Air Quality Sensor
in my arduino project I use the Adafruit CCS811 Air Quality Sensor Breakout - VOC and eCO2, I need the references and sizes of these components, knowing that I have found the electrical diagram but the values and references are not clear as you see in the photo.
Link to the sensor: https://learn.adafruit.com/adafruit-ccs811-air-quality-sensor/overview
Thank you in advance for your help.

What exactly is not clear? Do you need to know the physical size of each component? You can look at the PCB layout and then lookup the components with the corresponding packages. Their datasheets also include their size. Or do you want to know something different?

And wouldn't a question about an adafruit sensor be better suited for the Adafruit forum?