title: Input Capture Mode PPM signal

text:
# Question
Title: 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

# Answer
> 2 votes
> 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;

```

---
Tags: interrupt, timers, arduino-micro, atmega32u4, signal-processing
---


# Question
Title: 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.

# Answer
> 2 votes
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.

# Answer
> 1 votes
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.

# Answer
> 1 votes
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.

---
Tags: programming, interrupt, array
---


title: Save highlighted text as int variable

text:
# Question
Title: 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?

# Answer
> 3 votes
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.

---
Tags: keyboard
---


# Question
Title: 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).

# Answer
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));
}

```
> 0 votes

---
Tags: esp8266, programming, esp32
---


title: Explanation of code found online

text:
# Question
Title: 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;
}

```

# Answer
> 1 votes
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.

---
Tags: esp32, code-review
---


# Question
Title: How to read incoming HEX values from Serial.read() method?
***Brief description about the problem History***

Communicating with a old VersaStat II used GPIB port but the GPIB ports PCI card stopped working but there was a another port `25 pin rs232 Serial communication port` but even now, too bad computers are abending the Serial port luckily there is still `virtual Blutooth COM port` which can be used with a modern laptop so ***ESP32*** microcontroller was selected to communicate with this device wirelessly (might later go for HC05 module etc.).

***Fixing the voltage difference problem***

Now there is a big problem the esp32 Serial uses `+3.3 V` or logic `1` & `0 V` for logic `0` But in the rs232 port logic `0` is `+3 V ~ +12 V` and logic `1` is `-3 V ~ -12 V`  also `± 3V`  undefined region. To overcome this problem I have used the following circuit with ***optocouplers***.

Here is the circuit diagram

The following code was used to communicate with the device easy as seems

Code

```
#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;
int speedsend = 9600;

void setup() {
  Serial.begin(speedsend);
  Serial2.begin(speedsend);
  SerialBT.begin("ESP32SERIAL");
  delay(500);
}

void loop() {

  if (Serial2.available()) {
//incoming data from the device
    int i = Serial2.read();
    SerialBT.write(i);
    Serial.println(i); // To check what is coming as output
  }
  if (SerialBT.available()) {
    Serial2.write(SerialBT.read());
  }

}

```

But I see no meaningful characters in putty (Bluetooth COM port) in Arduino Serial I see some numbers in HEX representation. Is this the way old devices communicate?

This link show how HEX numbers correlate with ASCII characters

https://www.rapidtables.com/convert/number/hex-to-ascii.html

How to fix this issue am I doing something wrong in here the circuit parameters etc.

***Communication Example with device***

For a start the `ID` command should give a number as 2532 according to book after the conversion it gives me 32 32 34 32 0 0 , 2242 looking at the Arduino Serial numbers with the help of the converting web site shown in above url. That's how I noticed It gives me HEX numbers.

Here is the PDF rs232c Interface section PDF the original Book came with ID command page too.

https://drive.google.com/file/d/1BHhIsloF4voMxoFeSlz1GsjwfgHwgsPJ/view?usp=sharing

Another book looks same but not from the book came with

https://drive.google.com/file/d/1z0NUOe17SpVYTIBfEE8s0EKStfLKKv\_-/view?usp=sharing

# Answer
> 1 votes
Firstly you don't need that really complex optocoupler circuit. You just need a run-of-the-mill MAX3232 chip (note the extra 3 in there: it's the 3.3V version), that's what they're designed for: RS232 to 3.3V logic level conversion. You can pick up breakout modules for pennies on your favourite marketplace (ali-express, ebay, etc).

As for your reading, your assumption that your numbers are hexadecimal is completely wrong. They're decimal, not hexadecimal.

You read the data from the remote device and store each byte in an integer variable. Then you print that integer variable using `Serial.println()`. That will always give you a decimal representation of the numeric integer variable.

Your response of `32 32 34 32 0 0 , 2242` to my trained eye looks like bad communication. Maybe caused by your optocoupler circuit (change that for a MAX3232 immediately), or maybe caused by a mismatch in your baud rate, bit count, or parity settings.

# Answer
> 3 votes
Your problem is, that you try to provide a HEX value, but you are actually providing a decimal value.

When you just write a whole number like `32`, it will be interpreted by the compiler as a decimal number. The decimal number `32` is equal to HEX `20`, which is a space character in ASCII.

**Solution:** Write your number as decimal value like this:

```
int i = 0x32;

```

The `0x` preceding the value will mark it as a hexadecimal representation.

---
Tags: serial, esp32, string
---


# Question
Title: Does setting a value always mean setting a Arduino pin?
One thing that always confused me was why we use int or other commands to set the variables to have pin numbers as if those commands were always restricted to pin numbers only. For example

```
int ledPin = 13;

```

Does putting a random number in place of 13 that isn't a pin number cause an error? Right now I haven't checked yet.

I've only begun to realize that if you want to use variables in relation to pins or push buttons you have to set values first and then do associated functions like digitalRead. The commands like int are not like in other programming languages where you can set any values and do mathematical computations. I know it might seem obvious to someone who is used to Arduino, but this perspective is something that helped me grasp things better. Before that, I totally could not understand how things worked because of being confused with how int or other similar variables worked.

# Answer
Note that this is just a C/C++ integer declaration, assigning a value to a variable, like any variable (irrelevant if it is for pin numbers).

You don't have to use a variable, there are similar variations:

**Variable**

```
int pinNumber = 13;

```

in `begin`:

```
pinMode(pinNumber, OUTPUT);
digitalWrite(pinNumber, HIGH);

```

**Const**

Preferably I like to use a const:

```
const int PIN_NUMBER = 13;

```

Or even better, since it always is a low value:

```
const uint8_t PIN_NUMBER = 13;

```

And use it with capitals.

```
pinMode(PIN_NUMBER, OUTPUT);
digitalWrite(PIN_NUMBER, HIGH);

```

**#define**

```
#define PIN_NUMBER 13

pinMode(PIN_NUMBER, OUTPUT);
digitalWrite(PIN_NUMBER, HIGH);

```

The reason variables are used, is that when you want to use another pin number, you only need to change it in one place, making the sketch better maintainable/adaptable.

I don't know what happens when you give an illegal number (you can try it out yourself).
> 1 votes

---
Tags: arduino-uno, programming, led, pins, digital
---


title: Program size optimization

text:
# Question
Title: Program size optimization
I am trying to spare a few bytes of program size. I faced a problem which I cannot understand and I hope somebody will help.

Look at this empty sketch, pleas. It takes just 444 bytes:

```
void setup()
{
}

void loop()
{
}

```

However, this one – 1332 bytes already!

```
void f() {
    Serial.println(1);
}

void setup()
{
}

void loop()
{
}

```

Why? It is supposed that function `f()` will be cut-off during the linkage stage. But it is not. And what can I do to cut such things off, since they are not used in the code?

# Answer
Using the `Serial` object pulls HardwareSerial0.o into your program linkage. This file defines, among other things, the ISRs (interrupt service routines) associated with the serial port. ISRs are defined using the `ISR()` macro from the acr-libc. This macro creates a function prototype and assigns some attributes to the function, including the `used` attribute which tells the linker that it should consider the function to be used, even if it cannot spot a single call to it within the compiled program. The ISR cannot then be removed, and it in turn keeps lots of code from the `Serial` implementation.

**Edit**: As pointed out by the busybee in a comment, although `f()` cannot be removed at link time, it can be removed at compile time if you give it the `static` qualifier. This has the added benefit of triggering a compiler warning:

> **warning**: '*void f()*' defined but not used \[**-Wunused-function**\]
> 7 votes

---
Tags: arduino-uno, compile, linker
---


title: Keep Alive for Arduino

text:
# Question
Title: Keep Alive for Arduino
Sometimes the arduino locks up for some reason. It would be nice to know why, but the problem is more general. I have found a hardware keep alive that resets the controller if it doesn't respond:

Arduino Keep Alive with AT-Tiny

This would work, but i wonder if there are there features like this built in to any of the processors that can be used in the Arduino environment (ESP8266, ESP32, or the like).

**Maybe folks know of a processor with the "Keep Alive" feature?**

**How would i determine if this "keep alive" feature is present for a specific processor?**

Thanks for any suggestions!

Mark

# Answer
Reference link: https://create.arduino.cc/projecthub/rafitc/what-is-watchdog-timer-fffe20

* Watchdog timers can be found in the datasheet. If there is no intervention to this module by the software, the MCU will be reset. basically, restarting all the functions.
* It is a bad idea to use WDT to solve your particular topic. You should try to fix the issue
* The external watchdog timers (Example: ADM8320) is more reliable than internal ones
> 1 votes

# Answer
personally, I have never experienced my Arduino crashing. I even have a board running for one of my university projects measuring temperature, time and resistance of a sensor and saves the data to a micro SD card that has been running for over 3 months from batteries without issues!

What do you mean by 'locks up'? If you run the blink programme, does that stop or does It work ok?

In the link you provide, the idea of resetting devices in a complex IOT project is a smart idea, but you run into the risk of having your issue repeating over and over again if you do not know what is causing the problem
> 0 votes

---
Tags: reset
---


# Question
Title: Connection Pro-Mini & ESP8266 using Serial
I wish to create a system consists of WEMOS mini & Pro-Mini sharing info using Serial ( one MCU is dedicated to react input-output, and second for MQTT commands ) sharing same Power input. From what I read in tutorials, at boot Serial wires have to be disconnected, in order to accomplish boot.

A) is that true that at boot Serial has to be disconnected?

B) is there a way that 2 MCU can be connected at all times, including reboot when needed ( such as power failures ) ?

# Answer
> A) is that true that at boot Serial has to be disconnected?

No, that is not true. However if you are using `Serial` to communicate on the Pro Mini you will need to disconnect the ESP8266 in order to program the Pro Mini as it will interfere with serial communication to the PC.

> B) is there a way that 2 MCU can be connected at all times, including reboot when needed ( such as power failures ) ?

Given that A) is a no, then B) is irrelevant. It will just boot.

The only caveat is that the ESP8266 will squirt some boot messages out of serial as it boots at 74880 baud, so you have to be able to cope with that noise in whatever protocol you design between the two boards.
> 1 votes

# Answer
> A) is that true that at boot Serial has to be disconnected?

Not exactly, if you're careful about what is communicating with what and when. That you protect against multiple things driving the same connection, etc. And you don't mind being very confused a lot of the time. And that you're holding one board in reset while the other is being programmed.

> B) is there a way that 2 MCU can be connected at all times, including reboot when needed ( such as power failures ) ?

If you don't have a compelling reason to avoid it, you may be better off using I2C between the two of them. Then your serial is left alone on both boards to behave as it normally does. You don't need to sort out conflicts between boards trying to use serial to talk to each other and trying to use their serial transceivers to talk to the host and the conclusion that results from the host and both boards all see traffic from different things. And you have an open collector setup between your two boards which makes independently powering them somewhat less of a problem.

If you do try to use the Pro Mini and ESP8266 USARTs connected together, you should have some series resistance in the connection between the FTDI (or whatever) TX signal and the RX on the Pro Mini. Or between the Pro Mini RX and the WEMOS TX. In other words, anywhere you have two pins driving what would otherwise by the same node in the circuit, you need some current limiting in case they drive in opposite directions, as will happen if you connect their serial connections together. If you look at the Wemos D1 mini schematic or the Arduino UNO, Nano, etc schematics you'll see they've inserted some resistance there for that reason. If you look at the Pro Mini schematic you'll see the FTDI TX line is connected directly to the AVR's RX.

Below you asked why you would need the FTDI connection. If you're not programming the Pro Mini and not using it power the Pro Mini, then you don't.

However, if you're thinking you're going to be able to program the Pro Mini using the serial transceiver on the Wemos and the connection between them, that isn't going to work. The Wemos serial transceiver's TX would be connected to its ESP8266's RX, which would be connected over to the Pro Mini's TX (not RX) because project is operating normally it needs to receive data from the Pro Mini on that pin. Allowing the Wemos serial transceiver to talk to the Pro Mini's RX would require you to wire it in a way that the two boards couldn't use their USARTs to talk to each other. The two usages are only compatible with two different wiring schemes.
> 1 votes

---
Tags: serial
---


# Question
Title: esp32 crashes when trying to dereference a pointer value
I have a websocket listener that is giving me a std::string of my message payload (I want the bytes) and I wrote a function that pulls each of the bytes out and puts them into 32 bit integer variables, adds that integer to an array of 32 bit integers, and passes back the pointer address:

```
uint32_t *get32BitInt(WebsocketsMessage message)
{
  std::string raw = message.rawData();
  uint32_t chunks[message.length() / 4];
  int chunkIndex = 0;
  for (int i = 0; i < message.length(); i += 4)
  {
    uint32_t chunk = 0;
    for (int j = 0; j < 4; j++)
    {
      chunk <<= 8;
      chunk |= raw.at(i + j);
    }
    chunks[chunkIndex] = chunk;
    chunkIndex++;
  }
  return chunks;
}

```

And I know that parsing and array building works because if I add a loop before I exit the overall function call it prints them out just fine.

And in the function that calls the parser I can print out the address of the pointer that was passed back.

But, as soon as I try to dereference anything my microcontroller crashes:

I know that I'm pretty green to pointers and I'm probably misunderstanding something, but I keep looking at docs and examples of passing arrays as pointers and it seems right.

Also, something worth noting is that it doesn't seem to be an issue with the actual number printing, because if I store the first number of the array into a variable and then try to print a line after the assignment the controller crashes after the assignment but before the next serial print:

# Answer
> 1 votes
Ah, one of my friends pointed out the issue. It's a scope snag:

> chunks is allocated on the stack in get32BitInt By returning a pointer to chunks, you are pointing to memory that is deallocated. Think of it as pointing to a member variable of a class that has already been destroyed
>
> when you try to dereference deallocated memory, bad things can happen. usually in debug the compiler makes sure you fail hard
>
> the easiest way to test this is to allocate chunks outside of that function and pass it in as a reference

So yeah, I was allocating memory within the scope of a function and then blowing that memory contents away when that functions scope ended.

I refactored my code to move the array outside of the scope of the parsing function and passed the pointer in to the parsing function to get populated:

```
void get32BitInt(WebsocketsMessage message, uint32_t *chunks)
{
  Serial.println("--------------------------------");
  Serial.println("raw parse:");

  std::string raw = message.rawData();

  // uint32_t chunks[message.length() / 4];
  int chunkIndex = 0;

  for (int i = 0; i < message.length(); i += 4)
  {
    uint32_t chunk = 0;
    for (int j = 0; j < 4; j++)
    {
      chunk <<= 8;
      chunk |= raw.at(i + j);
    }
    chunks[chunkIndex] = chunk;
    chunkIndex++;
  }

  Serial.println("parsed chunks:");
  for (int i = 0; i < 11; i++)
  {
    Serial.print(chunks[i], HEX);
    Serial.print(" == ");
    Serial.println(chunks[i], BIN);
  }

  Serial.println("--------------------------------");
}

void addWebsocketListener()
{

  client.onMessage([&](WebsocketsMessage message) {

    uint32_t gameFrame[message.length() / 4]; // *try moving gameFrame out of scope
    get32BitInt(message, gameFrame);

    Serial.print("game frame address: ");
    Serial.println((int)&gameFrame);

    Serial.println("storing first 32 bit integer in a variable");
    uint32_t firstNumber = *gameFrame;

    Serial.print("game frame first value: ");
    Serial.println(firstNumber, HEX);

    Serial.println("printing frame:");
    for (int i = 0; i < 11; i++)
    {
      Serial.println(gameFrame[i], HEX);
    }
  });
}

```

And now my controller isn't crashing :D

And now I understand scope when dealing with pointers a bit better :)

---
Tags: esp32, array, pointer
---


# Question
Title: 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.

# Answer
> 1 votes
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;

```

# Answer
> 1 votes
Use `cli();` to completely disable interrupt. Then use `sei();` to re-enable the interrupt if you need it later.

---
Tags: interrupt, timers, isr
---


# Question
Title: 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:

1. ArduinoCore
2. bootloader
3. 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!

# Answer
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.
> 1 votes

---
Tags: atmel-studio, arduino-zero, atmel, samd21g, mkrzero
---


# Question
Title: How do I switch between while loops before the current loop finishes? IR Remote + LED's
I have a project that requires rotation of a tank tread. I've simulated LED's to go off in a rotation using an IR Remote. I want to stop the clockwise rotation halfway through so I can immediately rotation counterclockwise.

Unfortunately, my code waits until after the complete rotation (or the complete while/if loop) to move into the ccw rotation loop. How do I code this to immediately switch between loops?

Here is my code:

```
#include <IRremote.h>

int RECV_PIN = 10;
int Switch = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;

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

  pinMode(2, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  irrecv.enableIRIn();         // Start the receiver
}

void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value);
    irrecv.resume();           // Receive the next value
  }

  while (results.value == 16615543)     // button 2: clockwise rotation
  {
    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(3, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }

  while (results.value == 16580863)     //power button - break other loops and wait for next IR transmission
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
  }

  while (results.value == 16619623)     // button 8: ccw rotation
  {
    digitalWrite(9, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(2, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(8, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(9, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(7, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(8, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(6, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(7, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(5, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(6, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(4, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(5, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(3, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(4, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)

    digitalWrite(2, HIGH);
    delay(500);                // Wait for 500 millisecond(s)

    digitalWrite(3, LOW);
    delay(1000);               // Wait for 1000 millisecond(s)
  }
}

```

# Answer
> 0 votes
> How do I code this to immediately switch between loops?

You don't. You remove the loops. You don't want them - they can never end, since there is no way for the results to change between iterations.

You have a fundamental misunderstanding of how IR remotes work. There can be no "while" since a remote sends a signal either just once per button press, or repeatedly while the button is held down, depending on the function the button is supposed to perform.

Instead all you can do is "If the button has been pressed then do something". There's no "It's currently pressed" or "It's been released", only "I got a signal that it's pressed".

# Answer
> 0 votes
In addition to Majenko's answer, what you should use is a so called State engine.

First you define an enum:

```
enum EState { Off, Clockwise, CounterClockwise };

EState _state;

```

In `setup` you set `_state` to some default value.

In `loop` you check for button changes, and set the state accordingly.

Then you act on the state:

```
switch (_state)
{
case EState::Off:
    {
        // Switch all off
        for (int n = 0; n < 9; n++)
        {
            digitalWrite(n, LOW);
        }
    }
    break;

case EState::Clockwise:
    ... See below

case EState::CounterClockwise:
    ... Similar as above
}

```

For the Clockwise and CounterClockwise states, you have to keep a variable, that increases every 100 ms, resets itself when going to the new state.

Depending on the step value, you do something. e.g. for the first two clockwise steps:

```
digitalWrite(2, HIGH);
delay(500);                // Wait for 500 millisecond(s)

digitalWrite(9, LOW);
delay(1000);               // Wait for 1000 millisecond(s)

```

you can make a switch like this inside the case you already have (or better: create a new function):

```
switch (_step)
{
case 0: // 0 ms
    digitalWrite(2, HIGH);
    break;

case 5: // 500 ms
    delay(1000);

...

```

Note it is a bit more clean to create a sort of hash/array but the above should work too. You can increase `_step` every 100 ms or only when the (counter)clockwise states are active.

---
Tags: programming, ir, wireless
---


# Question
Title: LEDs: difference between common anode and common cathode?
What is the difference in using a common anode and common cathode of the 7 Segment in interfacing with the Arduino? How can you change the code if we need to add another 7 Segment display?

How can you change the code to have a counter in backwards (from 0 to 9)?

```
const int ANODE = 2;

const int LED1 = 3;
const int LED2 = 4;   // pin for led 2
const int LED3 = 5;   // pin for led 3
const int LED4 = 6;   // pin for led 4

// now bottom row

const int LED5 = 7;
const int LED6 = 8;
const int LED7 = 9;
const int LED8 = 10;

int DELAY = 0;

void setup() {
  pinMode(ANODE, OUTPUT);  // common anode is obviously an output

  pinMode(LED1, OUTPUT);   // led are output for low will be on
  pinMode(LED2, OUTPUT);   // led 2 is output
  pinMode(LED3, OUTPUT);   // led 3 is output
  pinMode(LED4, OUTPUT);   // led 4 is output
  pinMode(LED5, OUTPUT);   // led 5 is output
  pinMode(LED6, OUTPUT);   // led 6 is output
  pinMode(LED7, OUTPUT);   // led 7 is output
  pinMode(LED8, OUTPUT);   // led 8 is output
}

void loop(){

  if (DELAY == 300){
    delay(100000);
  }

  digitalWrite(ANODE, HIGH);

  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, HIGH);
  digitalWrite(LED3, HIGH);
  digitalWrite(LED4, HIGH);
  digitalWrite(LED5, HIGH);
  digitalWrite(LED6, HIGH);
  digitalWrite(LED7, HIGH);
  digitalWrite(LED8, HIGH);

delay(1000);

  digitalWrite(LED1, LOW);
  delay(500);
  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, LOW);
  delay(500);
  digitalWrite(LED2, HIGH);
  digitalWrite(LED3, LOW);
  delay(500);
  digitalWrite(LED3, HIGH);
  digitalWrite(LED4, LOW);
  delay(500);
  digitalWrite(LED4, HIGH);
  digitalWrite(LED5, LOW);
  delay(500);
  digitalWrite(LED5, HIGH);
  digitalWrite(LED6, LOW);
  delay(500);
  digitalWrite(LED6, HIGH);
  digitalWrite(LED7, LOW);
  delay(500);
  digitalWrite(LED7, HIGH);
  digitalWrite(LED8, LOW);
  delay(500);
  digitalWrite(LED8, HIGH);

  delay(100);

  DELAY = DELAY + 150;
}

```

# Answer
A 7-segment is a packaged set of 8 LEDs (7 number-segments & 1 decimal point). Common anode means that the anode (positive) side of all of the LEDs are electrically connected at one pin, and each LED cathode has its own pin. So turning on any particular segment will involve running a current from this common anode (positive) pin to the particular cathode (negative) pin for the desired segment.

Common cathode means that the cathodes of all of the LEDs are common and connected to a single pin. The anode for each LED has its own pin. So driving one of these means running a current from the particular anode (positive) pin for the desired segment to the common cathode pin.

The way that you are diving the 7-segment involves using a separate pin to drive each segment, so you use 8 pins of the Arduino to drive the display. You will run out of digital pins if you try to add a second 7-segment. There are a couple of ways to address this. One is to add a 7-segment driver, like the CD4511. This limits you to being able to display only numerical digits, but uses only 4 pins of the Arduino per 7-segment.

Another, more versatile way is to add a serial-in to parallel out chip (74HC595, for example) to drive the 7-segment. This requires only two pins from the Arduino (data & clock), and they can be chained to have multiple 7-segments driven from those same 2 pins.
> 7 votes

# Answer
Basically you just need to change the HIGH's by LOW's and the LOW's by HIGH's.
> 2 votes

# Answer
Spent an hour trying to work it out, seems I have common anode leds. So you have to connect the anode to the 5V (on arduino), The voltages are then reversed, so use 255-v instead of v.

I think common cathode will be easier to understand and program for.
> 2 votes

# Answer
To add to the existing answers:

> For the arduino with \[its\] symmetrical ability to source and sink exactly the same amount of current then there is no preferred way.

That being said, if you are using a driver circuit like the MAX7219 (which makes interfacing many digits much simpler and requires far fewer pins), use the one specified by the datasheet. For example, the MAX7219 is designed to drive common-cathode LED displays.
> 1 votes

# Answer
You can easily test this in 123D Circuits, check this out: https://123d.circuits.io/circuits/1019227-7-segment-circuit

Click start simulation and then click on the buttons to light up the corresponding segment.
> -1 votes

---
Tags: arduino-uno, c++, led
---


# Question
Title: Chips & High voltage: Connected in Series?
I have 3 micro-controllers that will be connected to a battery, and I need to provide each of them between 3 and 5 volts maximum.

I have 3V batteries but they do not seem to provide enough power, while putting to of them in series would fry the chips as it busts the 6 volts max.

My question is, if I provide 9 volts to 3 chips connected in series, would current drop be distributed evenly to 3V across all chips, or would for example fry the first one?

simulate this circuit – Schematic created using CircuitLab

# Answer
> 3 votes
If you put three resistors of the same value in series, then you would get equal voltage division between them.

But chips are not like resistors. Their current usage is not constant and typically vary by orders of magnitude even within each clock cycle. See why this would be a problem?

If you have good 3V batteries that supply 3V up to the maximum current that the chips can draw, and the chips are rated to run reliably at 3V then there is another problem. Maybe you need decoupling capacitors across the chips?

---
Tags: attiny, battery, voltage
---


title: Timer Interrupt Collision

text:
# Question
Title: Timer Interrupt Collision
I am working with a MEGA2560 trying to implement velocity ramps for three steppers at the same time. The goal is to move to different positions applying accelerations and decelerations while finishing all of them at the same time.

In order to do so, from the distances to move of each of the motors, I calculate the amount of steps to do and the velocities for each of those steps in order to ensure that all the motors finish at the same time. For so, I use timers 3, 4 and 5 in compare mode. This way, at each interruption, I make the motors do one step and, after that, I set the new compare value for the timer in order to reach the new velocity to move at.

My problem is that, at some point, my interruptions crash and one of the motors stops working. This only happens under one condition: when motor 1 has to do 18 steps and motor 2, 34. In this case, both motors 1 and 3 finish but motor 2 gets stuck and does not move any more. Although, if its motor 1 who has to do 34 steps and motor 2, 18, everything works. Motor 1 is related to timer 3 and motor 2 to timer 4. This makes me think this must be related to the priorities of the interruptions.

In the following code you can see my interruptions:

```
ISR(TIMER3_COMPA_vect) {
    m1_step();
    m1_steps_done++;
    m1_configure_vel();
}
ISR(TIMER4_COMPA_vect) {
    m2_step();
    m2_steps_done++;
    m2_configure_vel();
}
ISR(TIMER5_COMPA_vect) {
    m3_step();
    m3_steps_done++;
    m3_configure_vel();
}

```

While, in the velocity configuration I have:

```

void m1_configure_vel() {

  if (m1_steps_done < m1_acceleration_steps) {
    m1_temp_vel = m1_temp_vel + acceleration;
  }
  else if (m1_steps_done <= (m1_steps - m1_acceleration_steps)) {
    m1_temp_vel = m1_temp_vel;
  }
  else if (m1_steps_done < m1_steps) {
    m1_temp_vel = m1_temp_vel - acceleration;
  }
  else {
    m1_temp_vel = 0;
    m1_finished = true;
  }
  if (m1_temp_vel <=0){
    m1_temp_vel = 0;
  }

  OCR3A = frequency_to_compare_value(m1_temp_vel);
}

```

As you can see, all I do here is, depending on the steps done by the motor and the amount of steps to do, I increase, maintain or decrease the motor's velocity and set the compare value for the timer.

The whole thing is that this code works fine, the ramps are calculated properly and motors move correctly. The problem is that, under the condition I explained before, interruptions may collide due to their priorities and one of them just stops to happen.

I was wondering if anyone had any idea or have faced something like this before.

# Answer
> 1 votes
I think the problem is being caused by the size of your ISR's. When using ISR's, it's important to make the code as short as possible and you should certainly avoid using any functions!

I would change each of your ISRs to:

```
ISR(TIMER3_COMPA_vect) {
    m1_steps_done++;
}
ISR(TIMER4_COMPA_vect) {
    m2_steps_done++;
}
ISR(TIMER5_COMPA_vect) {
    m3_steps_done++;
}

```

then, in the main loop of your code, you can change it so that if m1\_steps\_done, or m2\_steps\_done or m3\_steps\_done has increased, execute the step and configure functions

# Answer
> 0 votes
Another approach might be to use a single timer instead of 3 separate ones. Maintain 3 software counters and increment all of them on each interrupt, with separate limit tests and resets. This will be slightly slower, but there will be no possibility of collisions.

---
Tags: arduino-mega, timers, isr
---


# Question
Title: how to use Nano instead of Uno3 to operate DC motors
OK I have the Logitech G29 Wheel and Pedal setup that I use for my Racing Sim. On YouTube there is a gentleman (amstudio) who has used motors on the Gas and Brake pedals to give some realism to the Sim. To achieve this he used a Uno 3 and a motor shield. The motors used are those that you'd find in the XBox/PS4 controllers. It's my understanding that the Uno 3, Nano and Micro are the same in its basic form, meaning that the sketch he uses can be used on all 3. If this is true then I want to use the smallest footprint to achieve the Rumble effect.

**Question** is how do I wire up the Nano to do this and with the motors as small as they are is it really necessary to have a motor shield or H bridges?

I have taken a picture of his Uno setup. My aim here is to make it the smallest as it can be and still do the function of this mod' as this will be its only function. Any ideas on how best to go about this, The XBox Controller is rated at 5v @ 450mA. have included a picture showing his setup.thanks in advance

# Answer
> 1 votes
> It's my understanding that the Uno 3, Nano and Micro are the same in its basic form

Not exactly. The Uno and Nano use the same chip (the Atmega328p) and have the same pins broken out. The Arduino Pro Mini also uses that chip, but I think the pinout is a bit different. But mostly a code can be reused between these boards. The Arduino Micro uses an ATmega32U4, which is a different chip. Depending on the actual code, you might not be able to just reuse the code. Then you might have to change to code to use the Micros hardware.

> with the motors as small as they are is it really necessary to have a motor shield or H bridges?

I would say yes. A digital output pin of an Arduino can only supply 20mA of current over longer time (absolute maximum 40mA). Even very small motors can easily exceed that. As long as you don't know the exact needed current in worst case (like stalling the motor), you should assume, that it is more than 20mA. Also a running motor generates a lot of electrical noise and the coils can induce backcurrents, that might destroy the output hardware of the Arduino pin (for that you need a flyback diode). And lastly, if you want to change the direction of the motor, you absolutely need an H-bridge. Otherwise it is only on or off.

> Question is how do I wire up the Nano to do this

With H-bridges you normally need 3 pins to control the motor:

* The enable pin (often marked as EN) enables or disables the motor (run or stop). You normally use `analogWrite(en_pin, speed)` to control the speed of the motor. It will send a PWM signal with the given duty cycle to the enable pin.
* And you have 2 input pins (often marked as IN). They give you control over the direction.
    + `IN1` to HIGH and `IN2` to LOW will give you the first direction. Reversing to `IN1` LOW and `IN2` HIGH will give you the other direction. This will cause the H-bridge to lead the current through the motor in different directions.
    + Setting them to the same value will cause the motor to break (because that will short circuit the motors coil).

So you would wire 3 output pins of the Arduino to the mentioned pins on the H-bridge. It is up to you, what you want to use here. You can use a shield (which is normally the size of the Uno), you can use other ready to use motor driver boards (there are many) or you could build your own driver with a H-bridge chip and flyback diode.

---
Tags: arduino-nano
---


title: SPI read while writing?

text:
# Question
Title: SPI read while writing?
I'm working on a driver for an SPI device that returns some data (device status) while the command byte is still being written. Is there a way to read this status data using standard Arduino APIs or do I need to bit-bang to access it?

Here's what the SPI signals look like:

The 6 bits in red are the ones I'm interested in reading.

---

For context, the device in question is a Microchip MCP3561 ADC (MCP3X6X series). It has a bug (erratum 2) where the new-data-ready flag (`/DR_STATUS`) is not always set correctly. Part of the work-around involves reading the status bits mentioned above.

# Answer
> 2 votes
The `SPI.transfer()` method is designed to send a byte through the SPI port and, *at the same time* receive an incoming byte.

Usage pattern:

```
uint8_t byte_to_send = ...;
uint8_t received_byte = SPI.transfer(byte_to_send);

```

---
Tags: spi
---


# Question
Title: Elements excluded from buffer array output after given structure (ESP8266 WifiSniffer) (snifferPacket)
I am currently trying to determine how the ESP8266 WifiSniffer program by Kalanda works.

Here is the source code:

```
#include <Arduino.h>

extern "C" {
  #include <user_interface.h>
}

#define DATA_LENGTH           112

#define TYPE_MANAGEMENT       0x00
#define TYPE_CONTROL          0x01
#define TYPE_DATA             0x02
#define SUBTYPE_PROBE_REQUEST 0x04

struct RxControl {
//THESE HAVE AN EFFECT
// signed rssi:8; // signal intensity of packet
// unsigned rate:4;
// unsigned is_group:1;
// unsigned:1;
// unsigned legacy_length:12; // if not 11n packet, shows length of packet. NOT THIS
// unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
// unsigned Smoothing:1;
// unsigned Not_Sounding:1;
// unsigned:1;
// unsigned Aggregation:1;
// unsigned STBC:2;
// unsigned rxend_state:8;
// unsigned ampdu_cnt:8;
// unsigned channel:4; //which channel this packet in.

//THESE HAVE NO EFFECT
// unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
// unsigned damatch0:1;
// unsigned damatch1:1;
// unsigned bssidmatch0:1;
// unsigned bssidmatch1:1;
// unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
// unsigned HT_length:16;// if is 11n packet, shows length of packet. NOT THIS
 //unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
 //unsigned SGI:1;
 //unsigned:12; //HAS NO EFFECT
};

struct SnifferPacket{
    struct RxControl rx_ctrl; //RxControl is just a name, can be named anything (as long as you change other things)
    uint8_t data[DATA_LENGTH]; //DOES NOT HAVE EFFECT
//    uint16_t cnt; //THIS HAS NO EFFECT
//    uint16_t len; //THIS HAS NO EFFECT
};

// Declare each custom function (excluding built-in, such as setup and loop) before it will be called.
// https://docs.platformio.org/en/latest/faq.html#convert-arduino-file-to-c-manually
//static void showMetadata(SnifferPacket *snifferPacket);
//static void sniffer_callback(uint8_t *buffer, uint16_t length);
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data);
static void getMAC(char *addr, uint8_t* data, uint16_t offset);
void channelHop();

/**
 * Callback for promiscuous mode
 */
static void sniffer_callback(uint8_t *buffer, uint16_t length) {

  struct SnifferPacket *snifferPacket;
  snifferPacket = (struct SnifferPacket*) buffer;

  Serial.print("buffer size: ");
  Serial.print(sizeof(buffer));

  Serial.print(" length size: ");
  Serial.print(sizeof(length));

  Serial.print(" snifferPacket size: ");
  Serial.print(sizeof(snifferPacket));

  Serial.print(" START OF BUFFER OG: ");
  for (int i = 0; i < 20; i++){
    Serial.print((unsigned int) buffer[i], BIN);
    Serial.print(" ");
  }
  Serial.print(" END OF BUFFER OG ");

  showMetadata(snifferPacket);
}

static void showMetadata(SnifferPacket *snifferPacket) {

  unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];

  uint8_t version        = (frameControl & 0b0000000000000011) >> 0;
  uint8_t frameType      = (frameControl & 0b0000000000001100) >> 2;
  uint8_t frameSubType   = (frameControl & 0b0000000011110000) >> 4;
  uint8_t toDS           = (frameControl & 0b0000000100000000) >> 8;
  uint8_t fromDS         = (frameControl & 0b0000001000000000) >> 9;
  uint8_t moreFragments  = (frameControl & 0b0000010000000000) >> 10;
  uint8_t retry          = (frameControl & 0b0000100000000000) >> 11;
  uint8_t powerMgmt      = (frameControl & 0b0001000000000000) >> 12;
  uint8_t moreData       = (frameControl & 0b0010000000000000) >> 13;
  uint8_t protectedFrame = (frameControl & 0b0100000000000000) >> 14;
  uint8_t htcOrder       = (frameControl & 0b1000000000000000) >> 15;

  Serial.print(" START OF BUFFER: ");
  for (int i = 0; i < 20; i++){
    Serial.print((unsigned int)snifferPacket->data[i], BIN);
    Serial.print(" ");
  }
  Serial.print(" END OF BUFFER ");

  Serial.print(" DATASPAN START: ");
  printDataSpan;
  Serial.print(" DATASPAN END ");

  Serial.print(" frameControl: ");
  Serial.print(frameControl);

  Serial.print(" version: ");
  Serial.print(version);

  Serial.print(" Type: ");
  Serial.print(frameType);

  Serial.print(" frameSubType: ");
  Serial.print(frameSubType);

  Serial.print(" toDS: ");
  Serial.print(toDS);

  Serial.print(" fromDS: ");
  Serial.print(fromDS);

  Serial.print(" moreFragments: ");
  Serial.print(moreFragments);

  Serial.print(" retry: ");
  Serial.print(retry);

  Serial.print(" powerMgmt: ");
  Serial.print(powerMgmt);

  Serial.print(" moreData: ");
  Serial.print(moreData);

  Serial.print(" protectedFrame: ");
  Serial.print(protectedFrame);

  Serial.print(" htcOrder: ");
  Serial.print(htcOrder);

  Serial.print(" Ch: ");
  Serial.print(wifi_get_channel());

//  Serial.print(" rssi: ");
//  Serial.print(snifferPacket->rx_ctrl.rssi, BIN);

//  Serial.print(" RSSI: ");
//  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

  //Only look for probe request packets
//  if (frameType != TYPE_MANAGEMENT ||
//      frameSubType != SUBTYPE_PROBE_REQUEST)
//        //Serial.println();
//        return;

//  Serial.print(" RSSI: ");
//  Serial.print(snifferPacket->rx_ctrl.rssi, DEC);

  Serial.print(" Ch: ");
  Serial.print(wifi_get_channel());

  char addr[] = "00:00:00:00:00:00";
  getMAC(addr, snifferPacket->data, 10);
  Serial.print(" Peer MAC: ");
  Serial.print(addr);

//  uint8_t SSID_length = snifferPacket->data[25];
//  Serial.print(" SSID: ");printDataSpan
//  printDataSpan(26, SSID_length, snifferPacket->data);

  Serial.println();
}

static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
  for(uint16_t x = start; x < DATA_LENGTH && x < start+size; x++) {
    Serial.print(data[x]);
    //Serial.write(data[x]);
  }
}

static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
  sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}

#define CHANNEL_HOP_INTERVAL_MS   100
static os_timer_t channelHop_timer;

/**
 * Callback for channel hoping
 */
void channelHop()
{
  // hoping channels 1-13
  uint8 new_channel = wifi_get_channel() + 1;
  if (new_channel > 13) {
    new_channel = 1;
  }
  wifi_set_channel(new_channel);
}

#define DISABLE 0
#define ENABLE  1

void setup() {
  // set the WiFi chip to "promiscuous" mode aka monitor mode
  Serial.begin(115200);
  //delay(10);
  wifi_set_opmode(STATION_MODE);
  wifi_set_channel(1);
  wifi_promiscuous_enable(DISABLE);
  //delay(10);
  wifi_set_promiscuous_rx_cb(sniffer_callback);
  //delay(10);
  wifi_promiscuous_enable(ENABLE);

  // setup the channel hoping callback timer
  //os_timer_disarm(&channelHop_timer);
  //os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
  //os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}

void loop() {
  //delay(10);
}

```

I have noticed the `Serial.print` output directly from the `buffer` differs to the `Serial.print` output for the variable `snifferPacket` which is given attributes of the struct `RxControl`.

When the code is configured as normal, the raw buffer output (BUFFER OG) has 12 additional elements compared to the snifferPacket (BUFFER) output. Here is an example:

```
buffer size: 4 length size: 2 snifferPacket size: 4 START OF BUFFER OG: 10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0 10000000 0 0 0 11111111 11111111 11111111 11111111  END OF BUFFER OG  START OF BUFFER: 10000000 0 0 0 11111111 11111111 11111111 11111111 11111111 11111111 11011000 111 10110110 11010 10100010 1000001 11011000 111 10110110 11010  END OF BUFFER  DATASPAN START:  DATASPAN END  frameControl: 128 version: 0 Type: 0 frameSubType: 8 toDS: 0 fromDS: 0 moreFragments: 0 retry: 0 powerMgmt: 0 moreData: 0 protectedFrame: 0 htcOrder: 0 Ch: 1 Ch: 1 Peer MAC: d8:07:b6:1a:a2:41

```

Comparing just the two buffer outputs:

```
 - BUFFER OG: 10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0 10000000 0
   0 0 11111111 11111111 11111111 11111111
 - BUFFER: 10000000 0 0 0 11111111 11111111 11111111 11111111...

```

I've been able to identify parts of the first 12 elements:

```
1.  10100010 -> RCPI (RSSI) in two's complement format
2.  10000    -> Unknown
3.  11100110 -> Unknown
4.  1010000  -> Unknown
5.  0        -> Unknown, but constant
6.  0        -> Unknown, but constant
7.  0        -> Unknown, but constant
8.  0        -> Unknown, but constant
9.  0        -> Unknown, but constant
10. 0        -> Unknown, but constant
11. 1        -> Wi-Fi channel (in this example it's channel 1)
12. 0        -> Unknown, but constant

```

These 12 elements come before the 802.11 packet (starting with the frame header which begins at 10000000)

Through trial and error, I've been able to the identify parts of the code that effect the snifferPacket output. These are:

1. 14 attributes in the `RxControl` struct, titled as `THESE HAVE AN EFFECT`.

a. Commenting between 1-8 of any attributes: The last 4 elements appear in the `snifferPacket` output (`0 0 1 0`)

b. Commenting between 9-13 of any attributes: The last 8 elements appear in the `snifferPacket` output (`0 0 0 0 0 0 1 0`)

c. Commenting all 14 attributes: The last 11 elements appear in the snifferPacket output (`10000 11100110 1010000 0 0 0 0 0 0 1 0`)
2. `struct RxControl rx_ctrl;`, under `struct SnifferPacket`

a. Commenting out: All 12 elements appear in the snifferPacket output (`10100010 10000 11100110 1010000 0 0 0 0 0 0 1 0`)

So it's clear that there is an association between defining attributes and their exclusion from the snifferPacket output.

Note that leading 0s are part of an element are ignored are part of the output. For example:

```
 - 0100 = 100
 - 0000 = 0
 - 1000 = 1000

```

So my questions are:

1. What do each of the 12 elements represent?
2. Why is there a difference in the output between the output of the raw `buffer` and `snifferPacket`?
3. Why do only certain attributes effect the output of `snifferPacket`?
4. Why does commenting a greater number of attributes result in a greater number of elements reappearing, no matter which attributes are commented?

Thanks in advance.

# Answer
> What do each of the 12 elements represent?

Things in the header. That is off-topic for here.

> Why is there a difference in the output between the output of the raw buffer and snifferPacket?

snifferPacket is overlaid over the incoming buffer. That includes the "data" buffer which you are printing. The data buffer is only a portion of the snifferPacket.

> Why do only certain attributes effect the output of snifferPacket?

They are bit fields, and they are packed into bytes or words. The number and size of bit fields affects the number of bytes needed to contain them, and thus where in the structure the `data` array comes.

> Why does commenting a greater number of attributes result in a greater number of elements reappearing, no matter which attributes are commented?

See above. Also, the attributes must be there. Removing them will mean that other attributes don't point to the right bits in memory.

You should learn how C bit fields work. You can read more at the C++ reference here.
> 1 votes

---
Tags: serial, esp8266, wifi, struct, buffer
---


# Question
Title: Issue using Arduino Mega Timer2 with PinChange Interrupt
I was working on a program to measure the pulse width , for that I thought of using Timer 2 in Arduino mega along with pin change interrupt,

The program I have written is as follows

```
volatile float ovfCount = 0;

typedef struct{
  float curr_ovfCount,prev_ovfCount;
  uint8_t curr_tcnt2, prev_tcnt2;
  uint16_t width;
  bool stateHigh = true;
}Pulse;

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
   * Pin Change Interupt for
   * measuring the pulse width
   * from the receiver
   *
   */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCICR = B00000100; // activating 2 nd PCINT
  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6

  /*
   * 8 bit timer setup for counting
   * timer 2 is used
   */
   TCCR2B=0x00;
   TCCR2A = 0x00; // wave generation is normal:: all zeros
   TCNT2 = 0x00;
   TIFR2 = 0x00; // resetting all flags
   TIMSK2 = 0x01; //timer overflow enable
   TCCR2B = 0x01; // no prescaling

}

ISR(TIMER2_OVF_vect){
  ovfCount++;
}

ISR(PCINT2_vect){
  float ovf_count = ovfCount;
  uint8_t tcnt2 = TCNT2;

  if( (PINK & 1 << PINK0) & ch1.stateHigh ){
    //Low-High
    ch1.prev_ovfCount = ovf_count;
    ch1.prev_tcnt2 = tcnt2;
    ch1.stateHigh = false;
  } else if( ! ((PINK & 1 << PINK0) & ch1.stateHigh)){
//    High-Low
    ch1.curr_ovfCount = ovf_count;
    ch1.curr_tcnt2 = tcnt2;
    ch1.width = (256.0*(ch1.curr_ovfCount - ch1.prev_ovfCount) + (ch1.curr_tcnt2 - ch1.prev_tcnt2) ) * 1000 / 16e6;
    ch1.stateHigh = true;
  }

}

void loop() {
  Serial.println(ch1.width);
  pinMode(13, OUTPUT);
  digitalWrite(13,!digitalRead(13));
  delay(1000);

}

```

and the output I am getting is ,

```
16:22:05.667 -> 0
16:22:05.847 -> 927
16:22:06.826 -> 927
16:22:07.820 -> 1001
16:22:08.847 -> 1001
16:22:09.837 -> 1001
16:22:10.843 -> 1001
16:22:11.835 -> 1002
16:22:12.863 -> 1002
16:22:13.871 -> 1002
16:22:14.854 -> 1002
16:22:15.873 -> 1003
16:22:16.875 -> 1003
16:22:17.887 -> 1003
16:22:18.860 -> 1003
16:22:19.875 -> 1003
16:22:20.867 -> 1003
16:22:21.907 -> 1003
16:22:22.895 -> 1003
16:22:23.922 -> 1008
16:22:24.921 -> 1008
16:22:25.938 -> 1008
16:22:26.922 -> 1008
16:22:27.939 -> 1008
16:22:28.961 -> 1008
16:22:29.946 -> 1008
16:22:30.971 -> 1008
16:22:31.993 -> 1008
16:22:32.974 -> 1008
16:22:34.011 -> 1008
16:22:35.016 -> 1008
16:22:36.026 -> 1008
16:22:37.012 -> 1008
16:22:38.024 -> 1008
16:22:38.939 -> 1008
16:22:39.802 -> 906
16:22:40.638 -> 906
16:22:41.508 -> 844
16:22:42.345 -> 844
16:22:43.189 -> 842
16:22:44.059 -> 842
16:22:44.905 -> 843
16:22:45.750 -> 843
16:22:46.593 -> 842
16:22:47.428 -> 842
16:22:48.305 -> 842
16:22:49.139 -> 842
16:22:50.011 -> 845
16:22:50.839 -> 845
16:22:51.707 -> 842
16:22:52.539 -> 842
16:22:53.419 -> 842
16:22:54.260 -> 842
16:22:55.111 -> 842
16:22:55.975 -> 842
16:22:56.791 -> 842
16:22:57.642 -> 842
16:22:58.492 -> 842
16:22:59.372 -> 842
16:23:00.212 -> 842
16:23:01.046 -> 842
16:23:01.918 -> 842
16:23:02.775 -> 842
16:23:03.600 -> 849
16:23:04.473 -> 849
16:23:05.329 -> 842
16:23:06.159 -> 842
16:23:07.022 -> 842
16:23:07.862 -> 842
16:23:08.709 -> 842
16:23:09.574 -> 842
16:23:10.412 -> 843
16:23:11.292 -> 843
16:23:12.116 -> 848
16:23:12.996 -> 848
16:23:13.899 -> 848
16:23:14.779 -> 848

```

The output I am expecting is 1000 as the connection to the PCINT is directly form the digital pin13 of the Arduino and it is made to blink at that interval

I want to know

* What mistake I am making here in measuring the counts
* How can I generalise this method for measuring width of 6 channels simultaneously.

===== Edit after input from Edgar Bonet ===========

I have written a program , can you please tell me is this a good way to accomplish my requirement

```
volatile uint32_t ovfCount = 0;

struct Pulse {
  uint32_t last_toggle;
  uint32_t width;
  bool stateHigh;
  bool input_is_high;
  uint32_t get_width() {
    noInterrupts();
    uint32_t width_copy = width;
    interrupts();
    return width_copy;
  }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
     Pin Change Interupt for
     measuring the pulse width
     from the receiver

  */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6
  PCICR = B00000100; // activating 2 nd PCINT

  /*
     8 bit timer setup for counting
     timer 2 is used
  */
  TCCR2B = 0x00;
  TCCR2A = 0x00; // wave generation is normal:: all zeros
  TCNT2 = 0x00;
  TIFR2 = 0x00; // resetting all flags
  TIMSK2 = 0x01; //timer overflow enable
  TCCR2B = 0x01; // no prescaling

  DDRH = B00111000;
  fastPWM_init();

}

void fastPWM_init() {
  //    clearing
  TCCR4A = 0; TCCR4B = 0; TCCR4C = 0;
  //    Initializing
  TCCR4A = B10101010; // OC4A, OC4B, OC4C : ICR-WGM
  TCCR4B = B00011010; // ICR-WGM prescalar : 8
  //    Setting frequency
  ICR4 = 39999;
  //    Setting PWM
  OCR4A = 2000; OCR4B = 2000; OCR4C = 2000;
}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(PCINT2_vect) {
  uint8_t tcnt2 = TCNT2;
  uint32_t ovf_count = ovfCount;

  if ( bit_is_set(TIFR2, TOV2) && tcnt2 < 128 ) {
    ovf_count ++;
  }

  uint32_t time = ovf_count << 8 | tcnt2;

  pinChangeFunction(&ch1, time, PK0);
  pinChangeFunction(&ch2, time, PK1);
  pinChangeFunction(&ch3, time, PK2);
  pinChangeFunction(&ch4, time, PK3);
  pinChangeFunction(&ch5, time, PK4);
  pinChangeFunction(&ch6, time, PK5);

}

void pinChangeFunction(Pulse *channel, uint32_t time, uint8_t pin){
  channel->input_is_high = bit_is_set(PINK, pin);
  if (channel->input_is_high && !channel->stateHigh) {
    channel->stateHigh = true;
  } else if (! channel->input_is_high && channel->stateHigh) {
    channel->width = time - channel->last_toggle;
    channel->stateHigh = false;
  }
  channel->last_toggle = time;
}

void loop() {

  if(Serial.available() > 0){
    OCR4A = Serial.parseInt();
  }

  Serial.print(ch1.get_width() / 16e3);Serial.print("\t");
  Serial.println(ch6.get_width() / 16e3);

}

```

The PWM is only used for testing.

# Answer
> 1 votes
There are quite a few issues with this program. The most obvious is the use of floating point calculations in interrupt context. Interrupts should be served as fast as possible, and floating point is really slow on the AVR.

Some other issues:

* Interrupt flags should be cleared by writing a logic 1 to them, however silly it may sound.
* A couple if `&` operators in `ISR(PCINT2_vect)` are probably meant to be `&&`.
* The logic for detecting rising and falling edges is all wrong.
* There is no need to store so much data in the `Pulse` objects.
* `ch1.width` should be read with interrupts disabled in order to avoid a data race.
* There is a subtle race condition when reading `ovfCount` and `TCNT2`: if the timer overflows right when `ISR(PCINT2_vect)` starts running, that overflow will not be counted.

Here is a version of the program that attempts to fix all these points. I also changed it for running on an Uno (with pin 13 = `PB5` = `PCINT5`), so that I could test it:

```
/*
 * Pulse width via PCINT.
 *
 * https://arduino.stackexchange.com/questions/81688
 */

volatile uint32_t ovfCount = 0;

struct Pulse {
    uint32_t last_toggle;
    uint32_t width;
    bool stateHigh;
    uint32_t get_width() {
        noInterrupts();
        uint32_t width_copy = width;
        interrupts();
        return width_copy;
    }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

void setup() {
    Serial.begin(115200);
    pinMode(13, OUTPUT);

    /* Setup Pin Change Interrupt for detecting pulses. */
    PCMSK0 = _BV(PCINT5);  // sense change on pin 13 = PB5 = PCINT5
    PCIFR  = _BV(PCIF0);   // reset interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0_vect: pins PCINT[7:0]

    /* Setup Timer 2 for counting. */
    TCCR2B = 0;           // stop
    TCCR2A = 0;           // normal mode
    TCNT2  = 0;           // reset timer
    TIFR2  = _BV(TOV2);   // reset interrupt flag
    TIMSK2 = _BV(TOIE2);  // enable timer overflow interrupt
    TCCR2B = _BV(CS20);   // count at F_CPU/1
}

ISR(TIMER2_OVF_vect) {
    ovfCount++;
}

ISR(PCINT0_vect) {
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;

    // Was there an overflow that has not yet been accounted for?
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }

    uint32_t time = ovf_count << 8 | tcnt2;

    bool input_is_high = bit_is_set(PINB, PB5);
    if (input_is_high && !ch1.stateHigh) {  // low -> high
        ch1.stateHigh = true;
    } else if (!input_is_high && ch1.stateHigh) {  // high -> low
        ch1.width = time - ch1.last_toggle;
        ch1.stateHigh = false;
    }
    ch1.last_toggle = time;
}

void loop() {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(200);
    Serial.println(ch1.get_width() / 16e3, 5);
}

```

And here is the output:

```
1000.02349
1000.01959
1000.01916
1000.02496
1000.01959
1000.02032
1000.01947
1000.02795
1000.02642
1000.01855
1000.01916
1000.02105
1000.02490
1000.01782
1000.03033
1000.01898
...

```

The printed values are larger than 1000 because of the time needed to execute `digitalWrite()`.

Also note that an 8-bit timer running at the full CPU speed overflows every 16 µs. That's quite a lot of pressure on the CPU, and many operations will take longer that expected because of these interrupts. If I wanted to time something with single-cycle resolution, I would reach for a 16-bit timer. And I would prefer using input capture, although sadly only two input capture channels are available on the Mega (on pins 48 and 49).

---

**Edit**: Answering the questions in the comments.

> please have a look at my question edits and please advice.

I did not test it, but it seems to me this code should work. I would prefer, however, having a different interrupt for each channel. Otherwise, the successive calls to `pinChangeFunction()` can make the execution of this ISR quite long.

Also note that `Pulse::input_is_high` serves no useful purpose. Storing this value in the object slows down the ISR, as it has to access memory, whereas a local variable would be kept in a (much faster) internal CPU register.

> what will we do if we have 8 channels as in the radio receiver?

You could use 6 external interrupts and 2 pin change interrupts.

> Why did you take `tcnt2 < 128` when `tcnt2` max is 256?

This one is tricky. I'll try to explain the whole logic of the test.

Consider the following naive version of the ISR:

```
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}

```

There is a small chance that Timer 2 overflows at point A, i.e. while this ISR is executing its prologue and has not yet read `TCNT2`. If this happens, the `TIMER2_OVF` ISR will not run immediately, because we are already executing an ISR, and ISRs do not nest. Then, `ovfCount` is not updated. If this happens, we then read a value of `TCNT2` affected by the overflow, and a value of `ovfCount` that does not account for that overflow. We then combine together those inconsistent values into a `time` value that misses 256 timer ticks.

We can detect this situation by reading the `TOV2` flag in `TIFR2`. This flag is set only when there is a pending interrupt request for `TIMER2_OVF`, i.e. if the counter has overflowed and that overflow has not yet been accounted for in `ovfCount`. Thus the “fixed” ISR looks like this:

```
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    // ← B
    uint32_t ovf_count = ovfCount;
    // ← B
    if (bit_is_set(TIFR2, TOV2)) {
        ovf_count++;
    }
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}

```

With this, if the overflow happens at point A, we manage to compute the proper `time`. But consider now what would happen if the timer overflows at either of the points marked B, i.e. after reading `TCNT2` but before reading `TOV2`. If this happens, we read the pre-interrupt values of both `TCNT2` and `ovfCount`. No correction is thus needed for computing a consistent `time`. Yet, `TOV2` is raised when we test it: we then apply an unneeded correction, and we end up with a `time` that is too large by 256 ticks.

In order to fix this problem, we have to make sure the correction is applied if the overflow happens at point A, but not if it happens at point B. How can we tell apart those two situations? The answer is: by looking at the value recorded in `tcnt2`. In case A, the counter was read right after the overflow, so it had a very small value (close to 0) when it was copied to `tcnt2`. In case B, the counter was read when it was just about to reach the overflow, so it had a very large value (close to 255). If `TOV2` is set when we read it, this means an overflow happened during the very beginning of the current ISR, very close to the point where we read `TCNT2`. So the value recorded in `tcnt2` has to be either very small or very large. It cannot be in the middle (close to 128).

So we have to decide whether `tcnt2` is very small or very large. There are many possible values that could be used as a threshold. The most natural is the mid range: 128. It is also the most efficient to compute, as the compiler can optimize the comparison into a simple test of the most significant bit. Thus the final version of the test:

```
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }

```

---
Tags: arduino-uno, arduino-mega, programming, interrupt, timers
---


# Question
Title: Wemos Mini & Pro Micro Serial connection
While using a 3.3v Pro Mini & Wemos mini to communicate via Serial was successful, when tried with a 5v Pro Micro it fails.

To overcome different logic level I used a 10K + 20K resistors to lower Pro-Micro's 5v to 3.3v successfully to `Tx` and `Rx` pins. Also since they are on the same PCB, `GND` pins are connected and `RAW` to `5V` at wemos mini is also connected. At the moment, it is powered up using MCU's USB input ( tried to connect to Pro-Micro only, Wemos Only, and both ).

What might be the problem ?

# Answer
> 2 votes
You don't need a logic level conversion between 5 V Micro Arduino and 3.3 V Wemos D1 mini. The 5 V ATmega 328p reads 3.3 V as HIGH and the esp8266 can tolerate 5 V logic level for tests. For long term connection you can add logic level conversion with a voltage divider to convert the 5 V of ATmega TX to 3.3 V of esp8266 RX.

RX/TX pins on Arduino Mini are Serial. RX/TX pins on Arduino Micro are **Serial1**. Serial is only USB on Micro.

---
Tags: serial
---


# Question
Title: Send data string from Arduino UNO to ESP8266-01
Is there anyway to send a string from an Arduino UNO to a ESP8266-01 (one with only 8 pins RX, TX, CH-PD, vcc, ground, reset, GPIO0, GPIO2) without using without using AT commands. I've looked everywhere and from what I can see UART doesn't work and SoftwareSerial uses only AT commands. I am at my wits end. Can anyone help here? please.
I have tried Serial.write but only writes String and Esp8266 only receives ints.

I found some code I thought might work but so far I can see that the arduino is sending \<100.00:200:00\>, but on the esp8266 all I get is four backwards question marks

this is the code on the Arduino UNO

```
#include <SoftwareSerial.h>

SoftwareSerial ESPserial(2, 3); // TX | RX
 float water = 100.00;
 float battery = 200.00;
void setup()
{
    Serial.begin(9600);     // communication with the host computer
    //while (!Serial)   { ; }

    // Start the software serial for communication with the ESP8266
    ESPserial.begin(57600);

}

void loop()
{
   ESPserial.print("<");
          ESPserial.print(water,2);
          ESPserial.print(":");
          ESPserial.print(battery,2);
      ESPserial.print(">");
      Serial.print("<");
          Serial.print(water,2);
         Serial.print(":");
          Serial.print(battery,2);
      Serial.print(">");
     delay(10000);
}

```

and here is the code on the ESP8266

```
#include <SoftwareSerial.h>
#include <string.h>

SoftwareSerial ESPSerial(2,0);

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

String water;
String battery;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  ESPSerial.begin(57600);
  delay(10);

}

void loop() {
  // put your main code here, to run repeatedly:
  recvWithStartEndMarkers();
  showNewData();

 water= getValue(receivedChars, ':', 0);
  battery = getValue(receivedChars, ':', 1);
Serial.println(water);
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (ESPSerial.available() > 0 && newData == false) {
        rc = ESPSerial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }

```

The Arduino sends writes every 10 seconds and the esp prints the ???? every 10 seconds but with a lag.

I am not sure what the pin out to pin in should be. Right now I have the Arduino 2(TX) attached to the GPIO0 and the Arduino 3(RX) attached to the GPIO2.

Can someone look at my code and see what I am doing wrong. I thought I would send over two values because eventually I want to show water level and battery level.

# Answer
> 1 votes
I figured this out. send code is

Arduino Uno side

```
 f = String('<')+String("Hi")+String(',')+String(waterSensorOutValue)+String(',')+String(sensorBatValue)+String('>');

    Serial.print(f);

```

ESP side

```
const byte numChars = 32; char receivedChars[numChars]; char tempChars[numChars];        // temporary array for use when parsing // variables to hold the parsed data char messageFromPC[numChars] = {0}; float floatFromPC = 0; float floatFromPC2 = 0; boolean newData = false; //end stuff ti bring in string String f;  long itt = 500;
    long itt2 = 500;

void loop() {

  //new stuff string recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    } }

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

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

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    } }

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    floatFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC2 = atoi(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC2); } //end new stuff string

```

Then connect to wifi and upload to ThingSpeak.

I had to get rid of Softwareserial and connect the RX on the Arduino Uno to the TX on the ESP8266-01 and the TX on the Arduino Uno to the RX on the ESP8266-01.

Everything worked great till I changed from an Arduino UNO R3 to an Arduino Pro Mini for size and energy conservation.

With the wiring the same (I think) and the code the same the string (f) doesn't get sent over to the ESP. I don't see the TX led flashing on the Pro Mini when it should be transferring string(f) and nothing gets uploaded to ThingSpeak. Not sure why but I will post another question for that one. Thanks for everyone's help.

# Answer
> 2 votes
Sending data between Arduino and NodeMcu (Serial Communication)

youtube link (in French):

https://youtu.be/0TXmi9EgaCs

---
Tags: arduino-uno, esp8266, softwareserial
---


title: Reading SNMP V2 OID from ESP8266/ESP32

text:
# Question
Title: Reading SNMP V2 OID from ESP8266/ESP32
i need to read from my ESP32/ESP8266 some SNMP V2 OID values from my home printer: it exists a library/method that can do that?

I've seen some SNMP agents, but they works only with the devie as server and not as SNMP client.

Any thoughts?

# Answer
> 3 votes
Not sure if you found it, but there I created an SNMP Manager: https://github.com/shortbloke/Arduino\_SNMP\_Manager

There is also an SNMP Agent: https://github.com/0neblock/Arduino\_SNMP

I know this is a bit later than when you requested this info. But posting here in case it's still helpful to you or others that stumble over this question.

---
Tags: esp8266, library, esp32
---