# Question
Title: How real-time is an arduino (react to sensor)?
New to arduino here, sorry for asking what may be a trivial question.

I need to simulate an industrial machine at home. It operates in a cyclic motion, creating an event for every rotation / cycle. Imagine a turntable or wheel with a marker in one place.

What I would like is:

* Have a physical wheel which I turn one rotation every 300 msec. This is the length in time of a cycle.
* Read a marker on this wheel using a sensor, such as Sick or Omron. I have this already. Sensor can be PNP or NPN, providing a closed or open connection. I can go via an optocoupler if needed.
* Once a signal is seen, the arduino should send a (sequential) string using RS232 to a PC. Approximately 90 characters. It is not needed to wait for response.

My question is: would be time for arduino to do this be relatively constant - ie, send out the data at approximately same point in the cycle. Example: signal read at "12" on the clock, data sent around "5".

If possible, what sort of Arduino would I be looking at ?

Or do I need something more real-time for such project, like a PLC ?

# Answer
> one rotation every 300 msec.

300 ms is a *very long time* for an Arduino, even for an AVR-based one, like an Uno.

I did a little experiment. I generated (with an Arduino...) a periodic signal consisting of a 96 µs-wide negative pulse repeating every 300 ms. I sent that signal to an Arduino Uno running the following code:

```
const uint8_t sensor_pin = 3;

// 90-byte message.
const char message[] = "Korem ipsum dolor sit amet, consectetur "
        "adipiscing elit sed do eiusmod tempor incididunt\r\n";

void setup() {
    pinMode(sensor_pin, INPUT_PULLUP);
    Serial.begin(9600);
}

void loop() {
    if (digitalRead(sensor_pin) == LOW) {
        Serial.write(message);

        // Wait until the signal rises again.
        while (digitalRead(sensor_pin) == LOW)
            continue;
    }
}

```

This is not the nicest way to do edge detection, but for this simple test it will do. You may notice that I am not using interrupts for capturing the pulse: 96 µs is long enough to be captured with this simple `digitalRead()`. I then captured the input and output signals with a dual-channel pocket oscilloscope. Here is a screen capture:

The cyan trace at the top is the received pulse. The yellow trace below is the output of the serial port. The negative pulse on this trace that is almost coincident with the received pulse is the start bit. Then the signal rises to transmit the first data bit, which is a 1 (that's why I chose “K” rather than “L” as the first letter).

What you can see in this capture is that the latency of the Arduino is tiny at this scale: a small fraction of the duration of the start bit. What you cannot see is the jitter, which is quite large in *relative* terms, but still small compared to the time scales relevant to you. In short, the delay between the falling edge on the input and the falling edge of the serial port start bit fluctuates roughly between 10 and 20 µs. Yes, those are **micro**seconds. This delay is roughly 20,000 times shorter than the rotation period. If the signal is read at “12” on the clock, the start bit fires at 12 hours with 0 minutes and 2 seconds.

Note that, on the other hand, the time needed to send the message at 9600 b/s is 93.6 ms, a significant fraction of the rotation period. And I didn't look at the behavior of the USB-to-serial converter chip, which is another can of worms...
> 7 votes

# Answer
TLDR: any Arduino is probably sufficient for your purpose when done properly.

I'll assume a proper HIGH/LOW binary signal from the sensor, HIGH when it "sees" the marker, LOW when it doesn't.

What could go wrong?

1. You use `digitalRead()` to get the state of the digital input. Depending on the pulse width, you might not catch the high state. Use interrupts instead.
2. Sending the data over Serial port takes longer than a turn of the machine. 90 bytes at 9600 bit/s needs (90 bytes * 10 bits/byte / (9600 kbit/s) = 93ms. In 300ms, there's enough time to send the 90 bytes. And 9600 bit/s is quite slow: you can probably use 115200 bit/s on short or shielded wires.
3. "Approximately 90 characters": calculate everything for the maximum data that will eventually be sent
4. Getting the data on Arduino side takes too long. You didn't give details on where those 90 bytes come from. Asking 90 devices to each give you a byte of data might not be possible in 300ms.
5. Receiving the data on the PC side (or whatever) might be delayed, because it is buffered. Especially USB to Serial adapters have no guaranteed timing. Doing the math for USB devices is hard.
6. Threading on the PC side: due to the OS Thread scheduling, the application that shall receive the data might not get CPU time for several milliseconds, 16ms (1/64s) is quite common. Doing the math is impossible (try running 8 real time threads that do something else and your PC is basically frozen)
7. Processing on the PC side: unknown
8. Displaying: after processing until a signal is displayed on the screen, that may take another 16 ms (at 60 Hz refresh rate).

> would be time for Arduino to do this be relatively constant

Relatively: yes. It certainly depends on the implementation (the Arduino C++ code).

If the data to send is hard coded 90 characters, I would expect the complete signal has been sent at before the 4 o'clock mark (94ms /300ms * 12 hours ~ 3 hours) . I see the problem more on the receiving side (see points 5., 6., 7. and 8.).

> what sort of Arduino would I be looking at ?

I don't know all of them, but an Uno will certainly work. If you only have that one digital input, even smaller ones are probably ok. Just start with an Uno or what you have available and see how it goes.

> do I need something more real-time for such project, like a PLC?

I don't see a need for a PLC in your project.
> 2 votes

---
Tags: serial, sensors
---


# Question
Title: Temperature sensors are heating themselves
I have 2 IoT devices for measuring room temperature. Room does not have direct sunlight (it is north oriented and have tree in front of window). One is ESP8266 with DHT11 and next one is ESP8266 with DS18B20. DHT is on the table, away from PC. DS18B20 is on the top of bookshelf next to plant. Both of them shows temperature around 32-33 deg. celsius. It is not that hot in the room for sure. My home thermostat shows 23-24 deg. celsius. Outside temperature is about 15 deg. When I open the window and cool down the room, I can see temerature drop on both sensors, but still ony to around 26-28 celsius. I think, they are overheating themselves.

Code is almost same on both devices. Sampling every minute, so it should not be an issue of overloading sensors. Supply voltage is 3,3V. Not parasitic with 2k2 pull-up resistor.

What should I do to get correct temperature reading from these sensors?

EDIT: I have tired to get sensor out of PCB. First, I have just raised it for lengt of its legs (about 1cm) above board. It helped little, but it is visible, that sensor started cold, and slowly saturated heat from wires. So I took quite thick cables (0,25mm^2) and put sensor about 10cm away from board. And it helped! Temperature is about 23 degrees, what is somwhere in expected range. Most important is, that temperature curve was dropping before stabilizing. Spikes are just 85°C first reading.

# Answer
> 2 votes
It seems, that problem is in heat transfer from ESP chip to thermometer via wires. Worst it was, when chip was on board itself, little bit better when it was raised about 1cm out of board. I have achieved correct readings only when I put sensor on longer and quite thick leads to avoid heat transfer as much as possible.

# Answer
> 0 votes
It does not surprise me that a sensor needs a correction to calculate the correct value. I have had the same problems with a range of sensors.

Because linearity is not really important when you need to measure only a room temperature, it would be sufficient to measure room temperature with a reliable thermometer and see how much you need to subtract to correct the value from your sensor. When still in doubt, you could cover the sensor with a plastic bag and measure the temperature dipped in a bowl of water with crushed ice cubes in it.

---
Tags: esp8266, temperature-sensor
---


# Question
Title: Seeeduino XIAO read PWM duration (period) using timers change Pins freom D2 to D1
I designed a circuitboard and need to proof the function.Therefore i have to modify the code to read from Pins D1 instead of D2. Unfourtunatly i am not that familar with the high level programming so im not sure if i got all changes. Basically all PINS on the circuit are used.

Basecode foud here: Seeeduino XIAO write and read PWM duration (period) using timers

Reading short square waves with Seeeduino XIAO pin D2

```
// Setup TC4 to capture pulse-width and period on digital pin D2 on Seeeduino Xiao
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;

void setup()   {
  SerialUSB.begin(115200);                         // Initialise the native serial port
  while(!SerialUSB);                               // Wait for the console to open

  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;           // Switch on the event system peripheral

  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz system clock by 1 = 48MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 4

  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                      GCLK_GENCTRL_GENEN |         // Enable GCLK 4
                      GCLK_GENCTRL_SRC_DFLL48M |   // Set the clock source to 48MHz
                      GCLK_GENCTRL_ID(4);          // Set clock source on GCLK 4
  while (GCLK->STATUS.bit.SYNCBUSY);               // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TC5
                      GCLK_CLKCTRL_GEN_GCLK4 |
                      GCLK_CLKCTRL_ID_TC4_TC5;

  // Enable the port multiplexer on port pin PA10
  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
  // Set-up the pin as an EIC (interrupt) on port pin PA10
  PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;

  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10;                                // Enable event output on external interrupt 10
  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH;                            // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10;                               // Disable interrupts on external interrupt 10
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                                        // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                                        // Wait for synchronization

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) |   // Set event generator (sender) as external interrupt 10
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0

  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |               // Enable the TC event input
                            //TC_EVCTRL_TCINV |              // Invert the event input
                            TC_EVCTRL_EVACT_PPW;           // Set up the timer for capture: CC0 period, CC1 pulsewidth

  TC4->COUNT32.CTRLC.reg = TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)

  TC4->COUNT32.INTENSET.reg = TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts

  TC4->COUNT32.CTRLA.reg = //TC_CTRLA_PRESCSYNC_PRESC |      // Overflow on precaler clock, (rather than the GCLK)
                           TC_CTRLA_PRESCALER_DIV1  |      // Set prescaler to 1, 48MHz/1 = 48MHz
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode

  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization
}

void loop() {
  if (periodComplete)                             // Check if the period is complete
  {
    noInterrupts();                               // Read the new period and pulse-width
    period = isrPeriod;
    pulsewidth = isrPulsewidth;
    interrupts();
    SerialUSB.print("PW: ");
    SerialUSB.print(pulsewidth);
    SerialUSB.print(F("   "));
    SerialUSB.print("P: ");
    SerialUSB.println(period);
    periodComplete = false;                       // Start a new period
  }
}

void TC4_Handler()                                // Interrupt Service Routine (ISR) for timer TC4
{
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x18);      // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;                    // Copy the period
    periodComplete = true;                                 // Indicate that the period is complete
  }

  // Check for match counter 1 (MC1) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC1)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x1A);      // Offset address of the CC1 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPulsewidth = TC4->COUNT32.CC[1].reg;                // Copy the pulse-width
  }
}

```

Do i only have to change the IOs: from:
PORT-\>Group\[PORTA\].PINCFG\[10\].bit.PMUXEN = 1;
PORT-\>Group\[PORTA\].PMUX\[10 \>\> 1\].reg |= PORT\_PMUX\_PMUXE\_A;
to:
PORT-\>Group\[PORTA\].PINCFG\[4\].bit.PMUXEN = 1;
PORT-\>Group\[PORTA\].PMUX\[4 \>\> 1\].reg |= PORT\_PMUX\_PMUXE\_A;

or do i need to mod more code?

Thanks for helping.

# Answer
In addition to the changes you mentioned, your `EIC_EVCTRL_EXTINTEO10`, `EIC_INTENCLR_EXTINT10`, and `EVSYS_ID_GEN_EIC_EXTINT_10` usages will need to be changed to `EIC_EVCTRL_EXTINTE4`, `EIC_INTENCLR_EXTINT4` and to `EVSYS_ID_GEN_EIC_EXTINT_4`, to re-target the event system source, because `PORT_PMUX_PMUXE_A` on both these pins routes the signal to the EIC, but not to the exact same interrupt number. The `EIC->CONFIG` line needs to change to the first group of 8 (`[0]`) and fourth SENSE within that group (`EIC_CONFIG_SENSE4_HIGH`) to the change to D1 (PA04) uses EXTINT4. This is something I'd left out of the first edit before I'd been able to test. I did eventually find a XIAO to test with and these modifications seem to make it work just fine on digital pin 1 now instead of digital pin 2.

```
EIC->EVCTRL.reg    |= EIC_EVCTRL_EXTINTE4;
EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;
EIC->INTENCLR.reg   = EIC_INTENCLR_EXTINT4;
EIC->CTRL.reg      |= EIC_CTRL_ENABLE;
while (EIC->STATUS.bit.SYNCBUSY);

```

...

```
EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |
                     EVSYS_CHANNEL_PATH_ASYNCHRONOUS |
                     EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |
                     EVSYS_CHANNEL_CHANNEL(0);

```

---

The changes you'd mentioned and those I've said above as diff:

```
--- original.ino
+++ modified.ino
@@ -24,14 +24,14 @@
                       GCLK_CLKCTRL_GEN_GCLK4 |
                       GCLK_CLKCTRL_ID_TC4_TC5;

-  // Enable the port multiplexer on port pin PA10
-  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
-  // Set-up the pin as an EIC (interrupt) on port pin PA10
-  PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;
+  // Enable the port multiplexer on port pin PA04
+  PORT->Group[PORTA].PINCFG[4].bit.PMUXEN = 1;
+  // Set-up the pin as an EIC (interrupt) on port pin PA04
+  PORT->Group[PORTA].PMUX[4 >> 1].reg |= PORT_PMUX_PMUXE_A;

-  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10;                                // Enable event output on external interrupt 10
-  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH;                            // Set event detecting a HIGH level
-  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10;                               // Disable interrupts on external interrupt 10
+  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO4;                                 // Enable event output on external interrupt 4
+  EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_HIGH;                            // Set event detecting a HIGH level
+  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT4;                                // Disable interrupts on external interrupt 4
   EIC->CTRL.reg |= EIC_CTRL_ENABLE;                                        // Enable EIC peripheral
   while (EIC->STATUS.bit.SYNCBUSY);                                        // Wait for synchronization

@@ -40,7 +40,7 @@

   EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                        EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
-                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) |   // Set event generator (sender) as external interrupt 10
+                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_4) |    // Set event generator (sender) as external interrupt 4
                        EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0

   TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |               // Enable the TC event input

```
> 0 votes

---
Tags: seeeduino-xiao
---


# Question
Title: Best practice for wiring two sensors that have SCL and SDA connections
I have two different sensors which have SCL and SDA connections which I am trying to connect to an Arduino nano. From what I understand, connecting both of these sensor to the A5 and A4 pins doesn't make any sense, considering that I need to collect data continuously from both sensors. Moreover, there are no other pins with the same functionality as A5 and A4. I am a beginner learning about microcontrollers, but it seems to me like the best practice to follow here would be to use two Arduino nanos. Is this this the only way, or is there another method I am not aware of?

# Answer
The whole point of the I2C bus is to allow multiple sensors or devices to be connected, as long as they have different I2C addresses. The addresses are usually built into the part, and often they have some provision for selecting an address from a range.

Whilst you can't *simultaneously* collect data from two sensors at once, you can certainly query them in quick succession. You need to connect SDA, SCL, Ground and +5V to each sensor, and the Arduino.

Your code would do something like:

* Query sensor at address 42
* Query sensor at address 43
* Do something with the data
* Wait a bit before doing it again

You could look at Wikipedia for some general information about I2C, and I also have a page about I2c that might help you.

Note that you also need a pull-up resistor on both SDA and SCL (that is, two resistors), a typical value would be 4.7k (connect the 4.7k resistors between SDA/SCL and your +5V line).
> 1 votes

---
Tags: arduino-nano, sensors
---


# Question
Title: No matching function for call to'DS3231 (const uint8_t &, const uint8_t &)
This was supposed to be the code for automatic pet feeder Got it from here

The problem is that I always got a "No matching function for call to'DS3231 (const uint8\_t &, const uint8\_t &)"

Here's the error code

```
Arduino: 1.8.19 (Windows 10), Board: "Arduino Uno"

ANA_FEEDER_PROJECT:53:18: error: no matching function for call to 'DS3231::DS3231(const uint8_t&, const uint8_t&)'

 DS3231 rtc(A4, A5);

                  ^

In file included from C:\Users\SERIES\Desktop\ANA_FEEDER_PROJECT\ANA_FEEDER_PROJECT.ino:1:0:

D:\Documents\Arduino\libraries\DS3231/DS3231.h:67:3: note: candidate: DS3231::DS3231(TwoWire&)

   DS3231(TwoWire & w);

   ^~~~~~

D:\Documents\Arduino\libraries\DS3231/DS3231.h:67:3: note:   candidate expects 1 argument, 2 provided

D:\Documents\Arduino\libraries\DS3231/DS3231.h:66:3: note: candidate: DS3231::DS3231()

   DS3231();

   ^~~~~~

D:\Documents\Arduino\libraries\DS3231/DS3231.h:66:3: note:   candidate expects 0 arguments, 2 provided

D:\Documents\Arduino\libraries\DS3231/DS3231.h:62:7: note: candidate: constexpr DS3231::DS3231(const DS3231&)

 class DS3231 {

       ^~~~~~

D:\Documents\Arduino\libraries\DS3231/DS3231.h:62:7: note:   candidate expects 1 argument, 2 provided

D:\Documents\Arduino\libraries\DS3231/DS3231.h:62:7: note: candidate: constexpr DS3231::DS3231(DS3231&&)

D:\Documents\Arduino\libraries\DS3231/DS3231.h:62:7: note:   candidate expects 1 argument, 2 provided

C:\Users\SERIES\Desktop\ANA_FEEDER_PROJECT\ANA_FEEDER_PROJECT.ino: In function 'void setup()':

ANA_FEEDER_PROJECT:84:7: error: 'class DS3231' has no member named 'begin'

   rtc.begin();

       ^~~~~

C:\Users\SERIES\Desktop\ANA_FEEDER_PROJECT\ANA_FEEDER_PROJECT.ino: In function 'void loop()':

ANA_FEEDER_PROJECT:130:10: error: 'class DS3231' has no member named 'getTimeStr'; did you mean 'getMinute'?

  t = rtc.getTimeStr();

          ^~~~~~~~~~

          getMinute

ANA_FEEDER_PROJECT:146:16: error: 'class DS3231' has no member named 'getTimeStr'; did you mean 'getMinute'?

  lcd.print(rtc.getTimeStr());

                ^~~~~~~~~~

                getMinute

ANA_FEEDER_PROJECT:152:16: error: 'class DS3231' has no member named 'getDateStr'; did you mean 'getDate'?

  lcd.print(rtc.getDateStr());

                ^~~~~~~~~~

                getDate

exit status 1

no matching function for call to 'DS3231::DS3231(const uint8_t&, const uint8_t&)'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

```

The problem is that I always got a "No matching function for call to'DS3231 (const uint8\_t &, const uint8\_t &)"

Here's the error code

# Answer
> 3 votes
You are using the wrong DS3231 library. Unfortunately, you can often find incompatible libraries that share the same name. The sketch you downloaded has been written for a specific version of the DS3231 library. Thus your choices are:

* either you use that specific version (linked to in the page you gave as reference)
* or you adapt the code to work with the version you have installed.

---
Tags: arduino-uno, arduino-ide, lcd, servo, keypad
---


# Question
Title: How to upload code to Arduino without a laptop
I would like to know is there a way of burning programs to microcontrollers like that on Arduino without using a computer? Like a pendrive or something? Suppose you want to update firmware on a utility end, must you carry the editable source code with you? How do the big companies do it?

# Answer
One good way to update Uno/Nano/Mini without connecting it to a computer is to use SD bootloader. SD bootloader reads at boot the bin file with the update from the attached SD card and copies it to flash memory.

There are not many SD bootloader for ATmega. I use avr\_boot by zevero. It works well. The downside is that it doesn't support upload over USB.

zevero doesn't offer built binaries of the bootloader so you have to compile it with the avr toolchain.

avr\_boot requires a bin file, not a hex file, but it is simple to set Arduino IDE to create a bin file along with the hex file. You create platform.local.txt file next to platform.txt in the avr boards package, and put this line into the file:

```
## Create output (bin file)
recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" -O binary {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"

```

Then you can use "Export compiled binary" from Sketch menu in Arduino IDE and you will find the binary file next to your ino file in the sketch folder.

---

There are different ways how to update an Arduino without connecting it to computer. For small ATmega328p on Uno/Nano/Mini there is not enough flash space to do a self update. The code required to do the update takes more than half of the flash so there is no space left to store the update binary before applying it. (The updated sketch of course must have to have the code for the self update too.)

For illustration what is possible, here is a sketch for Arduino Mega which does a self update from SD card reading a hex file. It requires a modified Optiboot available in MegaCore.
> 2 votes

---
Tags: arduino-uno, hex
---


# Question
Title: Do we have to calibrate LDR before using it in a project?
I am doing a project with Arduino, making a synthesizer, in which an LDR is used.

Before connecting the Arduino to a power source and use the project, do I need to calibrate the LDR like it is explained in Arduino website ?

# Answer
An LDR is a pretty inaccurate device. It just gives you a number which relates to darkness or brightness. How do those numbers relate to darkness and brightness? Well, only in a very vague way. All you can really say with any confidence is that bigger numbers mean brighter light, and smaller numbers mean darker darkness.

Even after "calibration" the numbers are pretty meaningless in any real-world sense.

All the "calibration" does is give a rough guide to the range of the numbers produced in any given lighting situation. It's then up to you to program your sketch in such a way that it works within the ranges of those numbers.

And yes, those numbers will change depending on the current lighting situation.

You could incorporate some form of "calibration" routine in your sketch to adjust any relevant values and calculations, or you could just provide some interface for tweaking values. Or your system may just really not care. It's impossible to know until you actually start creating your system.
> 2 votes

# Answer
My application was a little different. My illumination/light source was fixed (and exact). I compensated the sensor for temperature. The results I obtained were very exact and repeatable.

Here are my temperature compensation results.
> 1 votes

---
Tags: photoresistor, calibration
---


# Question
Title: ISR for timer on Arduino MEGA gets called only once
I am trying to write an Arduino code to blink LED using timer 4 on Arduino MEGA (atmega2560). I resetted the timer registers, and entered all the necessary values to bring to 16MHz to 1Hz (rescalar = 1024, OCR4B = 15624), then I wrote the blinking code inside the service routine block. Now when I run the program, the ISR is called **only once**. I saw from Youtube videos that even though the setting up of TCCR registers and TIMSK is in setup() function, it repeats indefinitely like a loop. Below is my code. Any help would be immensely appreciated. Thank you.

```
int led_pin = 10;
static int counter = 0;
int led_blink = 0;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(led_pin,OUTPUT);
cli();
TCCR4A = 0;
TCCR4B = 0;
TCNT4 = 0;
OCR4B = 15625;                                //set the maximum count 16MHz -> 1Hz
TCCR4B |= (1<<CS10) | (1<<CS12) | (1<<WGM12); // prescalar = 1024 , CTC(OCR3B) mode
TIMSK4 |= (1<<OCIE4B);
sei();
interrupts();
}

ISR(TIMER4_COMPB_vect)
{
  Serial.println(millis());
  led_blink = !led_blink;

}

void loop() {
  // put your main code here, to run repeatedly:
  if(led_blink == 1)
    digitalWrite(led_pin,HIGH);
}

```

# Answer
> 1 votes
Your missing an else statement in your loop:

```
else
  digitalWrite(led_pin,LOW);

```

---
Tags: timers, atmega2560
---


# Question
Title: How to turn off the display of line numbers on Mac Arduino IDE?
I'm trying to turn off line numbers on the Mac Arduino IDE but don't see the option for it after navigating to `Arduino IDE > Preferences`. Below is a screenshot of what I am seeing.

I saw this question asked previously, but there is no `File > Preferences` path on Mac. I am using Version 2.0.0 on macOS (10.14 or newer).

# Answer
> 6 votes
I don't see a proper place to do this in the 2.0.0 IDE preferences. However, modifying the .arduinoIDE/setting.json file to include `"editor.lineNumbers": "off",` seems to work.

```
{
 "editor.lineNumbers": "off",
 "editor.fontSize": 14,
 ...
}

```

Edgar Bonet pointed out in a comment that there's still a bunch of empty space in that region. The image above doesn't do a good of showing why though. In the below screenshots I've told the IDE to set a breakout and hovered over where folding region so it displays the fold indicators to make somewhat easier to see that and compare what effect on width results from disabling these things.

If you want to save a bit more space you can add turn off the code folding feature, which removes the spaced that would be used for fold indicators with an additional `"editor.folding": "false",` in the settings.json file.

For comparison, here's everything enabled, numbers but no folding, folding but no numbers, no folding and no numbers:

I haven't yet found out how to turn off the display of break-point indicators. I assume that it is possible though.

---
Tags: arduino-ide
---


title: Duinotech ATTINY85 Pinout

text:
# Question
Title: Duinotech ATTINY85 Pinout
I'm sure this is a super nooby question but,

what is the pinout of the Digispark ATTINY85 Development Board

The board looks like this:

Now the reason why I'm asking this question, when I do `digitalWrite(1, HIGH);`, the test light will come on. My question is then, what is the virtual number for PB1 (P1 in photo).

Also, does that arduino output + or -?

Any help is appreciated. Thank You!

# Answer
This seems to show an obvious pinout with an LED connected to p1 (digital pin 1). With "virtual number" I guess you mean the Arduino pin nr. As your code shows you, it's Arduino pin 1.
> 0 votes

---
Tags: pins, digispark
---


title: Bluetooth Arduino Data Type Error

text:
# Question
Title: Bluetooth Arduino Data Type Error
In my code I want to send some float values from my phone to the Arduino's Bluetooth which I will then split using the substring function. it will then print that split value to the serial monitor.

I don't even know what is wrong but there is no error and it just spits out the ascii code of those numbers (not split). Please help if anyone has any idea. Here is my code:

```
#include <Wire.h>
#include<SoftwareSerial.h>
#define TxD 3
#define RxD 2
SoftwareSerial bluetoothSerial(TxD,RxD);

String Sstring;
String arrayOne;

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

void loop()
{

 if(bluetoothSerial.available()>0)
 {

  arrayOne=bluetoothSerial.read();

  Sstring=arrayOne.substring(0);
  Serial.println(Sstring);
 }
}

```

# Answer
> 1 votes
First thing, you have to decide what data format the phone application will use for sending the data to the Arduino: define a “language” of sorts. Then you have to program both the phone and the Arduino to speak that same language.

Unless the data throughput is critical, I strongly advise you to use a text-based format, where each “message” is followed by a dedicated character that signals the end of the message. Popular choices for the message terminator are `'\n'` (ASCII line feed, numeric value 0x0a = 10), `'\r'` (carriage return = 0x0d = 13) and `';'` (semicolon = 0x3b = 59). The semicolon is often used as a second-level separator, to split a message into smaller fields.

Here is a simple example that reads one-line messages, using a line feed as a delimiter:

```
void loop() {
    if (bluetoothSerial.available() > 0) {
        String message = bluetoothSerial.readStringUntil('\n');
        Serial.println(message);
    }
}

```

If you want to send the data as binary, then message framing becomes a tricky problem. Since every possible byte value can legitimately appear within the message (any byte can appear within a float), you cannot simply reserve one byte to serve as a terminator. This is why, unless you are an advanced programmer, I strongly encourage you to send whatever data you want to send as text. Text also makes debugging much easier.

Finally, I have to warn you that the `String` class is not friendly to the memory of your Arduino, and can lead to instabilities if used extensively. If you have time, I encourage you to study the robust way to read text from the serial port: see the article Reading Serial on the Arduino, by Majenko.

# Answer
> 0 votes
I'm guessing the line `arrayOne=bluetoothSerial.read();` is converting the received value to a string (character array of ASCII charachters terminated with the '\0' character). Then, you copy that string to another string variable. If you want to split the string you should:

* define a starting character \> 0
* and/or: define an ending character \< the total string size.

See this link for more info.

You could try the following. I'm sure it's far from perfect but it might get you a bit further.

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

void loop()
{
    if (bluetoothSerial.available)
    {
        delay(100); // wait a little for the serial buffer to saturate. This value should be as short as possible

        // Save the buffer bytes as the float (Big Endian!)
        double received_float = (bluetoothSerial.read() << 24) | (bluetoothSerial.read() << 16) | (bluetoothSerial.read() << 8) | (bluetoothSerial.read());
        Serial.println(received_float);
    }
}

```

Some conciderations:

* The nr of bytes a float occupies may differ on your phone and your Arduino. The example above uses a 32-bit float
* If possible you'd want to start the transmission with a sequency of starting characters. That way, you can be sure to read the proper value.

---
Tags: arduino-uno, bluetooth
---


# Question
Title: Attiny timer interrupt does not make an interrupt every 1000ms
I'm making a stopwatch using an attiny85, the idea was to use the timer interrupts to count the seconds my theory was: since I set the Attiny85 to run at 1Mhz, I can use a presale of 1024; 1000000 / 1024 = 976.5625 hz, 976.5625hz = 1.024ms, 125ms / 1.024ms = 122.07, so that I need to count to 122 to get a 125ms interrupt, then in the ISR function I can count to 8 to get around 1 second, ( 122 * 1.024 ) * 8 = 999.424ms

What is the problem? well, the problem is that I'm not getting something close to 999.424ms, I compere it with my phone's stopwatch and the attiny seems to start well, but then it gets about 2-3 slower than my phone's stopwatch

```
#include <TM1637Display.h>

#define CLK 4
#define DIO 3
#define button 1

TM1637Display display (CLK, DIO);
int intr_count = 0;
byte dots = 0b01000000;

volatile int seg;
volatile int min;
volatile bool start = false;

void setup() {
  display.setBrightness(5);
  display.clear();
  pinMode(button, INPUT);

  cli();

  TCCR0A  = 0;
  TCCR0B  = 0;
  TCCR0B |= B00000101;
  TIMSK  |= B00010000;

  OCR0A   = 122;

  sei();
}

void start_counting(){
  if (digitalRead(button) == HIGH){
    start = !start;
    if(start == false){
//    display.clear();
      seg = 0;
      min = 0;
    }
    while(digitalRead(button) == HIGH);
  }
}

void loop() {
  start_counting();
  display.showNumberDecEx(min, dots, true, 2, 0);
  display.showNumberDec(seg, true, 2, 2);

}

ISR(TIMER0_COMPA_vect) {
  TCNT0 = 0;
  if(start == true){

    if (intr_count == 8) {

      seg++;

      if(seg == 60){
        min++;
        min = min % 60;
      }

      seg = seg % 60;

      intr_count = 0;
    } else {
      intr_count++;
    }
  }
}

```

# Answer
I see three issues with this approach.

The first is that you are using a very low quality, uncalibrated time source. The frequency of the internal RC oscillator is good to within a few percent only. It is also very unstable, and hugely dependent on temperature. Using an external 16 Mhz ceramic oscillator should give you a frequency that is no worse than 0.5% off, with a typical error about 0.1%. It is still somewhat unstable though. If you instead are using a *crystal* oscillator, then you can expect an error about ten times smaller (in the range of 100 ppm), and a very good stability. Depending on you quality requirements, 100 ppm may still not be good enough, in which case you still have the option to measure the drift rate and calibrate it out (see below).

The second problem, which has already been raised by 6v6g, is that your timer is counting from zero to 122 inclusive, which gives a period of 123 timer clock cycles. Take a look at the timing diagrams in the datasheet if you need to convince yourself of this. If you want a period of 122, you should set OCR0A to 121.

The third problem is that you are resetting the timer with the ISR. This may work in this program, but it is a very fragile approach worth avoiding. The problem is that everything the microcontroller does takes time, and your ISR may even get delayed by another interrupt. If the timer is incremented after rising the interrupt flag but before you reset it, you are missing one count. If you want to have a continuous time scale, *never* reset your timer. You can either:

* let it run continuously, undisturbed (and do `OCR0A += 122` within the ISR),
* or let it reset itself by using the appropriate waveform generation mode (CTC or fast PWM).

Lastly, here is a trick you may use to calibrate your stop watch. Instead of counting the interrupts until the counter reaches 8 (which assumes an interrupt period of exactly 1/8 s), increment a nanosecond counter within the ISR, and count one second once you have one billion nanoseconds:

```
const uint32_t nanoseconds_per_interrupt = 124928000;

ISR(TIMER0_COMPA_vect) {
    static uint32_t nanoseconds;
    nanoseconds += nanoseconds_per_interrupt;
    if (nanoseconds >= 1000000) {
        nanoseconds -= 1000000;
        seconds++;
        // then update minutes, hours... if needed
    }
}

```

This will increment the seconds every eight interrupts... most of the time. From time to time, however, it will take nine interrupts. This adds a little bit of jitter, but prevents the timing errors from accumulating and making the clock drift. If the jitter is visible, you can reduce it by shortening the interrupt period.

The value 124928000 I wrote above assumes the ISR is called every 122×1024 cycles of a 1 MHz clock. You can change it to fit a different clock frequency or a different OCR0A setting. The trick is: once you measure the drift rate of your stop watch, you can tweak this number to remove that drift. For example, if you measure the stopwatch and find it is running 0.04% too slow, then you increase that number by 0.04% (that would give 124977971) and the drift is gone.

**Edit**: In a comment, 6v6gt pointed out a fourth issue in your code, which is likely the biggest issue. Your logic for counting interrupts is:

```
if (intr_count == 8) {
    intr_count = 0;
} else {
    intr_count++;
}

```

This is counting from 0 to 8 *inclusive*, and looping with a period of 9 interrupts. A safer idiom for looping with a period of 8 would be:

```
if (++intr_count >= 8) {
    intr_count = 0;
}

```

Although I would still recommend counting nanoseconds if you want the ability to calibrate your clock.
> 4 votes

---
Tags: interrupt, time, attiny85
---


title: Does the bootloader use some SRAM?

text:
# Question
Title: Does the bootloader use some SRAM?
I want to use all SRAM of an Arduino by writing the code in assembly. But does the bootloader use some SRAM while the program is running, and if the answer is *yes* would changing that data lead to failure or does the data stored there get corrupted? Thanks for reaching out.

# Answer
You did not specify what type of Arduino you are using. My answer is for the AVR-based ones.

The bootloader does use RAM *while it is running*. However, once it handles control to your program, the microcontroller is all yours: you are free to use all the RAM.

Id did not check with optiboot but, it is possible that the bootloader leaves some stuff in the stack. The C runtime of the avr-libc takes care of this: one of the first things it does is to reset the stack pointer. If you link with the avr-libc, you will find the stack empty. If you don't, I suggest you set the stack pointer to RAMEND at the beginning of your program, just in case.
> 5 votes

---
Tags: sram, assembly
---


title: Array of Functions

text:
# Question
Title: Array of Functions
I'm new to C++. How to make a menu without `if() {} else {}` & `switch() case`? I made a menu on an array, but for some reason it doesn't compile. How to correct it?

```
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);

class Menu {
public:
    Menu() {
        updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
    }

    static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
        cbDisplay = display;
        cbSetTime = setTime;
        cbSetAlarms = setAlarm;
        alarmHours = alarmHours;
        alarmMinutes = alarmMinutes;
        cbSetAlarms(alarmHours, alarmMinutes);
    }
    // Used for menu.UpDown(dir) callback
    static void UpDown(int8_t direction) {
        updownFn(direction);
    }
    // Used for menu.Tab() callback
    static void Tab() {
        updownFnNum++;
        updownFn = updownFns[updownFnNum % 5];
    }

private:

    static void updownNone(int8_t direction) { }

    static void updownAlarmHours(int8_t direction) {
        alarmHours += direction;
        cbDisplay(alarmHours, alarmMinutes);
        cbSetAlarms(alarmHours, alarmMinutes);
    }

    static void updownAlarmMinutes(int8_t direction) {
        alarmMinutes += direction;
        cbDisplay(alarmHours, alarmMinutes);
        cbSetAlarms(alarmHours, alarmMinutes);
    }

    static void updownTimeHours(int8_t direction) {
        timeHours += direction;
        cbSetTime(timeHours, timeMinutes);
        cbDisplay(timeHours, timeMinutes);
    }

    static void updownTimeMinutes(int8_t direction) {
        timeMinutes += direction;
        cbSetTime(timeHours, timeMinutes);
        cbDisplay(timeHours, timeMinutes);
    }

    static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
    static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
    static cbd cbDisplay;
    static cbt cbSetTime;
    static cba cbSetAlarms;
    static MenuFunction updownFns[5];
    static MenuFunction updownFn;
};

uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;

```

Output:

```
In file included from app.ino:7:0:
menu.h: In constructor 'Menu::Menu()':
menu.h:9:109: error: cannot convert '<brace-enclosed initializer list>' to 'MenuFunction {aka void (*)(signed char)}' in assignment
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};

```

Thank you!

# Answer
The C++ language makes a distinction between an *initialization* and an *assignment*. An initialization is the initial value you give to a variable at the point where you are defining it. An assignment is the use of the `=` operator anywhere else. Also, the language does not allow assigning the contents of an array as a whole. You can initialize an array though.

This:

```
Menu() {
    updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes,
        updownTimeHours, updownTimeMinutes};
}

```

is an attempt to assign a whole array. It cannot work. If you want to initialize the array, do it at the point where it is being defined, outside of the class definition:

```
MenuFunction Menu::updownFns[5] = {updownNone, updownAlarmHours,
    updownAlarmMinutes, updownTimeHours, updownTimeMinutes};

```
> 2 votes

# Answer
First, your `updownFns[5]` can be contain 5 variable. And the last variable index can be 4 not 5 because of array index starts from 0.

Here is the code :

```
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);

class Menu {
public:
    Menu() {
        updownFns[0] = updownNone;
        updownFns[1] = updownAlarmHours;
        updownFns[2] = updownAlarmMinutes;
        updownFns[3] = updownTimeHours;
        updownFns[4] = updownTimeMinutes;
    }

    static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
        cbDisplay = display;
        cbSetTime = setTime;
        cbSetAlarms = setAlarm;
        alarmHours = alarmHours;
        alarmMinutes = alarmMinutes;
        cbSetAlarms(alarmHours, alarmMinutes);
    }
    // Used for menu.UpDown(dir) callback
    static void UpDown(int8_t direction) {
        updownFn(direction);
    }
    // Used for menu.Tab() callback
    static void Tab() {
        updownFnNum++;
        updownFn = updownFns[updownFnNum % 5];
    }

private:

    static void updownNone(int8_t direction) { }

    static void updownAlarmHours(int8_t direction) {
        alarmHours += direction;
        cbDisplay(alarmHours, alarmMinutes);
        cbSetAlarms(alarmHours, alarmMinutes);
    }

    static void updownAlarmMinutes(int8_t direction) {
        alarmMinutes += direction;
        cbDisplay(alarmHours, alarmMinutes);
        cbSetAlarms(alarmHours, alarmMinutes);
    }

    static void updownTimeHours(int8_t direction) {
        timeHours += direction;
        cbSetTime(timeHours, timeMinutes);
        cbDisplay(timeHours, timeMinutes);
    }

    static void updownTimeMinutes(int8_t direction) {
        timeMinutes += direction;
        cbSetTime(timeHours, timeMinutes);
        cbDisplay(timeHours, timeMinutes);
    }

    static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
    static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
    static cbd cbDisplay;
    static cbt cbSetTime;
    static cba cbSetAlarms;
    static MenuFunction updownFns[5];
    static MenuFunction updownFn;
};

uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;
// MenuFunction Menu::updownFns = {};

```

But still code is not correct. if you look at the signature of this definition

```
typedef void (*cba)(uint8_t, uint8_t, uint8_t);

```

it takes 3 parameters. But inside the code, you give 2 parameter to the function

```
cbSetAlarms(alarmHours, alarmMinutes)

```
> 0 votes

---
Tags: arduino-ide, c++, array, callbacks
---


# Question
Title: Problem with character concatenation algorithm in matrix led
good afternoon, I am making a 7x10 led matrix in which I use a CD4017 to handle the 7 rows and 2 cascaded shift registers to handle the 10 columns. I first tried a programming to turn on my entire led matrix and it worked fine. Then, I tried to make a character appear statically and it worked fine. Next, I tried to make that character sweep from right to left and it worked fine. But, what I am having a hard time with is sweeping the message from right to left smoothly with a column of character to character spacing.

What I originally thought is that if I wanted to move a character from right to left, I have to shift the column values for all the rows by an appropriate amount (shift step) and once the character has been shifted enough, I start feeding the column values of the next character in the message for which, the formula that would create the right to left shift effect is: (current\_char\<scroll) | (next\_char\>\>(8-shift\_step)-scroll) But I don't get the expected result, the message scrolls from right to left but it doesn't do it with a column of separation between character and character and it doesn't do it in a fluid way either. In addition to that at the end of sweeping the message appears something strange that should not be there.

I recorded a video showing what I am saying: https://drive.google.com/file/d/1ebO5zassWY060mvWACPhcSLeOi5JmZAC/view

Code:

```
/*
 char_data is a two dimensional constant array that holds the 5-bit column values
 of individual rows for ASCII characters that are to be displayed on a 7x10 matrix.
*/
const byte char_data[95][7]={
    {0, 0, 0, 0, 0, 0, 0}, // space
    {0b100, 0b100, 0b100, 0b100, 0b100, 0, 0b100}, // !
    {0b1010, 0b1010, 0b1010, 0, 0, 0, 0}, // "
    {0b1010, 0b1010, 0b11111, 0b1010, 0b11111, 0b1010, 0b1010}, // #
    {0b100, 0b1111, 0b10100, 0b1110, 0b101, 0b11110, 0b100}, // $
    {0b11000, 0b11001, 0b10, 0b100, 0b1000, 0b10011, 0b11}, // %
    {0b1000, 0b10100, 0b10100, 0b1000, 0b10101, 0b10010, 0b1101}, // &
    {0b100, 0b100, 0b100, 0, 0, 0, 0}, // '
    {0b100, 0b1000, 0b10000, 0b10000, 0b10000, 0b1000, 0b100}, // (
    {0b100, 0b10, 0b1, 0b1, 0b1, 0b10, 0b100}, // )
    {0b100, 0b10101, 0b1110, 0b100, 0b1110, 0b10101, 0b100}, // *
    {0, 0b100, 0b100, 0b11111, 0b100, 0b100, 0}, // +
    {0, 0, 0, 0, 0b100, 0b100, 0b1000}, // ,
    {0, 0, 0, 0b11111, 0, 0, 0}, // -
    {0, 0, 0, 0, 0, 0, 0b100}, // .
    {0, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0}, // /
    {0b1110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b1110}, // 0
    {0b110, 0b1100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // 1
    {0b1110, 0b10001, 0b1, 0b110, 0b1000, 0b10000, 0b11111}, // 2
    {0b11111, 0b1, 0b10, 0b110, 0b1, 0b10001, 0b1111}, // 3
    {0b10, 0b110, 0b1010, 0b10010, 0b11111, 0b10, 0b10}, // 4
    {0b11111, 0b10000, 0b11110, 0b1, 0b1, 0b10001, 0b1110}, // 5
    {0b01110, 0b10001, 0b10000, 0b11110, 0b10001, 0b10001, 0b1110}, // 6
    {0b11111, 0b1, 0b10, 0b100, 0b1000, 0b1000, 0b1000}, // 7
    {0b01110, 0b10001, 0b10001, 0b1110, 0b10001, 0b10001, 0b1110}, // 8
    {0b01110, 0b10001, 0b10001, 0b1111, 0b1, 0b10001, 0b1110}, // 9
    {0, 0, 0b100, 0, 0b100, 0, 0}, // :
    {0, 0, 0b100, 0, 0b100, 0b100, 0b1000}, // ;
    {0b10, 0b100, 0b1000, 0b10000, 0b1000, 0b100, 0b10}, // <
    {0, 0, 0b11111, 0, 0b11111, 0, 0}, // =
    {0b1000, 0b100, 0b10, 0b1, 0b10, 0b100, 0b1000}, // >
    {0b1110, 0b10001, 0b1, 0b10, 0b100, 0, 0b100}, // ?
    {0b1110, 0b10001, 0b10111, 0b10101, 0b10110, 0b10000, 0b1111}, // @
    {0b1110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // A
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b11110}, // B
    {0b1110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b1110}, // C
    {0b11110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b11110}, // D
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111}, // E
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000}, // F
    {0b1110, 0b10001, 0b10000, 0b10111, 0b10101, 0b10001, 0b1110}, // G
    {0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // H
    {0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b11111}, // I
    {0b1, 0b1, 0b1, 0b1, 0b1, 0b10001, 0b1110}, // J
    {0b10001, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001, 0b10001}, // K
    {0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111}, // L
    {0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001, 0b10001}, // M
    {0b10001, 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001}, // N
    {0b1110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // O
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000, 0b10000}, // P
    {0b1110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10011, 0b1111}, // Q
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b10001}, // R
    {0b1111, 0b10000, 0b10000, 0b1110, 0b1, 0b1, 0b11110}, // S
    {0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // T
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // U
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // V
    {0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b11011, 0b10001}, // W
    {0b10001, 0b10001, 0b1010, 0b100, 0b1010, 0b10001, 0b10001}, // X
    {0b10001, 0b10001, 0b1010, 0b100, 0b100, 0b100, 0b100}, // Y
    {0b11111, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b11111}, // Z
    {0b1110, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1110}, // [
    {0, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0}, // backward slash
    {0b1110, 0b10, 0b10, 0b10, 0b10, 0b10, 0b1110}, // ]
    {0, 0, 0b100, 0b1010, 0b10001, 0, 0}, // ^
    {0, 0, 0, 0, 0, 0, 0b11111}, // _
    {0b1000, 0b100, 0b10, 0, 0, 0, 0}, // `
    {0, 0, 0b1110, 0b1, 0b1111, 0b10001, 0b1111}, // a
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110}, // b
    {0, 0, 0b1110, 0b10001, 0b10000, 0b10001, 0b1110}, // c
    {0b1, 0b1, 0b1, 0b1111, 0b10001, 0b10001, 0b1111}, // d
    {0, 0, 0b1110, 0b10001, 0b11111, 0b10000, 0b1111}, // e
    {0b1110, 0b1001, 0b11100, 0b1000, 0b1000, 0b1000, 0b1000}, // f
    {0, 0, 0b1110, 0b10001, 0b1111, 0b1, 0b1110}, // g
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b10001}, // h
    {0b100, 0, 0b100, 0b100, 0b100, 0b100, 0b1110}, // i
    {0b1, 0, 0b11, 0b1, 0b1, 0b10001, 0b1110}, // j
    {0b10000, 0b10000, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001}, // k
    {0b1100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // l
    {0, 0, 0b11110, 0b10101, 0b10101, 0b10101, 0b10101}, // m
    {0, 0, 0b11110, 0b10001, 0b10001, 0b10001, 0b10001}, // n
    {0, 0, 0b1110, 0b10001, 0b10001, 0b10001, 0b1110}, // o
    {0, 0, 0b1111, 0b1001, 0b1110, 0b1000, 0b1000}, // p
    {0, 0, 0b1111, 0b10001, 0b1111, 0b1, 0b1}, // q
    {0, 0, 0b10111, 0b11000, 0b10000, 0b10000, 0b10000}, // r
    {0, 0, 0b1111, 0b10000, 0b1110, 0b1, 0b11110}, // s
    {0b100, 0b100, 0b1110, 0b100, 0b100, 0b100, 0b11}, // t
    {0, 0, 0b10001, 0b10001, 0b10001, 0b10011, 0b1101}, // u
    {0, 0, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // v
    {0, 0, 0b10001, 0b10001, 0b10101, 0b11111, 0b10101}, // w
    {0, 0, 0b10001, 0b1010, 0b100, 0b1010, 0b10001}, // x
    {0, 0, 0b10001, 0b10001, 0b1111, 0b1, 0b11110}, // y
    {0, 0, 0b11111, 0b10, 0b100, 0b1000, 0b11111}, // z
    {0b10, 0b100, 0b100, 0b1000, 0b100, 0b100, 0b10}, // {
    {0b100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // |
    {0b1000, 0b100, 0b100, 0b10, 0b100, 0b100, 0b1000}, // }
    {0, 0, 0, 0b1010, 0b10101, 0, 0} // ~
};
char message[] = "MATRIX LED 7X10 WITH ATMEGA328p";
int string_length = strlen(message);
byte shift_step = 1;

void setup(){
    // PORTB as output.
    // Pin 13: ClockRegister
    // Pin 12: Latch
    // Pin 11: Data
    // Pin 10: Reset
    // Pin 9: Clock4017
    DDRB = 0b111111;
    // Makes sure the 4017 value is 0.
    PORTB |= (1 << PB2);
    PORTB &= ~(1 << PB2);
    Serial.begin(9600);
}

void send_data(uint16_t data){
    uint16_t mask = 1, flag = 0;
    for (byte i=0; i<10; i++){
        flag = data & mask;
        if (flag) PORTB |= (1 << PB3);
        else PORTB &= ~(1 << PB3);
        PORTB |= (1 << PB5);
        PORTB &= ~(1 << PB5);
        mask <<= 1;
    }
    PORTB |= (1 << PB4);
    PORTB &= ~(1 << PB4);
}

void display_pattern(byte loops){
    for (byte c=0; c<string_length; c++){ // For each character
        for (byte scroll=0; scroll<10; scroll++){ // For each column.
            for (byte t=0; t<loops; t++){ // The delay we get with loops.
                for (byte z=0; z<7; z++){ // For each row.
                    // To obtain the position of the current character in the char_data array, subtract 32 from the ASCII value of the character itself.
                    byte index = message[c];
                    byte temp = char_data[index-32][z];
                    byte index_2 = message[c+1];
                    byte temp_2 = char_data[index_2-32][z];
                    send_data((temp<<scroll) | (temp_2>>(8-shift_step)-scroll));
                    delayMicroseconds(800);
                    // Clear the row so we can go on to the next row without smearing.
                    send_data(0);
                    // On to the next row.
                    PORTB |= (1 << PB1);
                    PORTB &= ~(1 << PB1);
                }
                // Select the first row.
                PORTB |= (1 << PB2);
                PORTB &= ~(1 << PB2);
            }
        }
    }
}

void loop(){
    display_pattern(10);
    delay(100000);
}

```

I appreciate the help.

# Answer
> 2 votes
Here are a few issues that I noticed in this code. I think that, if you manage to address them, you should get a smooth display:

1. In the expression `(temp_2>>(8-shift_step)-scroll)`, the amount of shift will be negative when `scroll` gets larger than 7. A righ shift by a negative amount is not a left shift: it is undefined behavior. Judging by the video, it seems the compiler does no shit at all in this case.
2. If you want a one pixel space between the characters, you should move to the next character in the string every six pixels, thus the scroll variable should count from 0 to 5.
3. Be aware that there could be up to three characters simultaneously (partially) displayed on the screen: when one character is centered, you should be able to see the edges of both its neighbors.
4. As noted by hcheung in a comment, when you get to the last character in the string, the expression `message[c+1]` is reading past the end of that string.

---
Tags: arduino-uno, atmega328, array, led-matrix
---


title: Conditional assignment of array

text:
# Question
Title: Conditional assignment of array
I have some really long global variable arrays filled with data.

There is a single function that processes the data. The function works on only one array everytime. This arrays value changes every iteration and gets the value from the global variable arrays.

Since i declare lots of global variable arrays, in order to pass them to the array\_to\_be\_processed\_by\_the function, the memory is filled up really quickly.

What is the best way to conditionally give values to the array?

For example, there could be a counter in the program, and if the counter is a particular value, the array would be initialized with certain data. Of course, i would also have to call the function, and i would have to keep track of the counter and increase it and zero it at the beginning of the loop, to start from the beginning.

In this approach, only one variable would always be initialized.

```
PSEUDOCODE:
int looper = 0;

void loop()
{
  switch(looper)
  {
     case 0:
        my_array[] = {DATA HERE};
        exec_func(myarray);
        looper++;
        continue;
     case 1:
         ......
     case 'last_case':
         ...
         looper = 0;
         break;
  }
}

```

However, i am not sure if this approach is the correct one. Especially for a microcontroller.

One obvious issue, is that the array values are not necessarily the same size. Therefore, the base array should be destroyed at each `case`? If this is good approach, should `new/delete` be used on an arduino?

What is the best approach to conditionally initialize an array, so that i don't get out of memory

# Answer
> 3 votes
Let's consider this:

```
case 0:
    my_array[] = {DATA HERE};
    exec_func(myarray);

```

This is not quite valid C++, but let's pretend you get the syntax right to make it work. The problem is: doing this will not help you save memory. Where do you think the compiler is going to store `{DATA HERE}`? In memory, right. It will be stored as an *anonymous* array. Then the initialization of `my_array` will make a *second copy* of the data in memory, this time in a named array.

You can avoid this second copy by naming your arrays of constants, and passing the correct one to your function:

```
// At global scope:
const int my_array_0[] = {...};
const int my_array_1[] = {...};

// Within the switch/case:
case 0:
    exec_func(my_array_0);

```

You can even avoid the `switch`/`case` altogether by using an array of pointers, but that is irrelevant to your current problem.

Your idea of initializing only the array you actually need can work if you manage to do it *procedurally*, i.e. implementing some recipe with instructions, rather than copying a set of constant:

```
case 0: {
    int my_array[array_size];
    for (int i = 0; i < array_size; i++) {
        my_array[i] = some_expression_to_compute_this_array_item;
    }
    exec_func(myarray);
}

```

This is not always feasible though.

If you really have to store the constants in the program, and you are using an AVR-based Arduino (like the Uno, Mega, Micro...), then you can save RAM by storing the arrays of constants in flash memory, and copying only the one you need to RAM:

```
// At global scope:
const int my_array_0[] PROGMEM = {...};
const int array_size_0 = sizeof my_array_0 / sizeof my_array_0[0];
const int my_array_1[] PROGMEM = {...};
const int array_size_1 = sizeof my_array_1 / sizeof my_array_1[0];

// Within the switch/case:
case 0: {
    int my_array[array_size_0];  // array in RAM
    memcpy_P(my_array, my_array_0, sizeof my_array);
    exec_func(my_array);
}
case 1: {
    int my_array[array_size_1];  // array in RAM
    memcpy_P(my_array, my_array_1, sizeof my_array);
    exec_func(my_array);
}

```

Check the documentations of PROGMEM and `memcpy_P()` for the details.

If you go this route, you may consider modifying the function `exec_func()` so that it expects its parameter to be a pointer to flash instead of a pointer to RAM. Then you will completely avoid the copy in RAM.

---

**Edit:** expanding on the idea of passing a pointer to flash.

The C++ compiler doesn't really know the difference between a pointer to RAM and a pointer to flash. If you want to pass a pointer to flash to a function, you have to write the function in such a way that it expects a pointer to flash. For example, this function prints out the contents of a flash-based array:

```
// The argument should be a pointer to flash.
void exec_func(const int *data)
{
    for (int i = 0; i < array_size; i++) {
        int number = pgm_read_word(&data[i]);
        Serial.println(number);
    }
}

```

Note that the array is not accessed directly (evaluating `data[i]` would give garbage). Instead, the address of the element you want (`&data[i]`, a flash address) is passed to the macro `pgm_read_word()`, which uses inline assembly to get the relevant data from the flash.

Now you can call this function passing it the address of a `PROGMEM` array, as in `exec_func(my_array_0);`.

Just for completeness, I will show you how to use an array of pointers to avoid the `switch`/`case` construct:

```
const int my_array_0[] PROGMEM = {...};
const int my_array_1[] PROGMEM = {...};
...

const int *arrays[] = {my_array_0, my_array_1, ...};

int looper = 0;

void loop()
{
    exec_func(arrays[looper]);
    if (++looper == number_of_arrays) looper = 0;
}

```

Note that here `arrays` is a RAM-based array. That's why you can access the elements directly as `arrays[looper]`. These elements, however, are pointers to flash-based arrays. If you have so many arrays that `arrays` gets too big, you might consider putting it also in flash.

---
Tags: array, variables, memory-usage, memory
---


title: I need help producing 2 pwm signals

text:
# Question
Title: I need help producing 2 pwm signals
My project is to use an Arduino to control two solenoid valves with PWM and receive an input signal from a sensor as feedback.

The valves direct the flow of water which cause a hydraulic actuator to move which is detected by an LVDT sensor.

What I want my program to do is to allow me to set a desired displacement as a goal which causes the Arduino to dynamically change the duty cycle of the pwm signal based off of the feedback input the Arduino receives. I am going to implement a PID to control it.

The circuit consist of the Arduino sending PWM signals to two logic level NPN mosfets to control the solenoids that are powered by 2 external 12V sources.

What I specifically need help with is how to write the part of the program that will let me produce 2 PWM signals that will allow me to change the frequency of the pwm waves so that the solenoids have enough time to switch and then also the ability to set the duty cycle.

I am a total novice programmer and its my first time working with electronics. I'm just hoping someone can point me in the right direction.

# Answer
> 4 votes
If you only need two PWM pins, I suggest using hardware PWM with Timer 1. The Timer 1 library makes the process quite easy. It supports frequencies from 0.12 Hz up to a few MHz, although the resolution degrades above 7.8 kHz.

Compared to an interrupt-based solution, hardware PWM has less jitter and it does not consume CPU cycles. The drawback is that you will be limited to 2 channels operating at the same frequency, but this doesn't seem to be an issue for your project.

# Answer
> 0 votes
You can try to use my **AVR\_Slow\_PWM** Library, which can provide these following features and generate 2 independent PWM signals to any GPIO pin. Certainly only if your hardware design can correctly use PWM signals.

> This library enables you to use ISR-based PWM channels on AVR-based boards, such as Mega-2560, UNO,Nano, Leonardo, etc., using AVR core to create and output PWM any GPIO pin. Because this library doesn't use the powerful purely hardware-controlled PWM with many limitations, the maximum PWM frequency is currently limited at 500Hz, which is still suitable for many real-life applications

# Answer
> 0 votes
Tacking on this as a belated observation more than anything else.

Since there is no indication of an accumulator on the hydraulic circuit and the two valves are working in opposition, it might be necessary to maintain both complementary PWM ratios and consistent relative phase.

The TimerOne library appears- by eye- to maintain a consistent relative phase. The AVR\_Slow\_PWM library definitely doesn't.

If it is /not/ necessary to apply an offset to the PWM edges to accommodate the valves having different open and close times then it might be easiest to simply change the switching sense of one of the FETs with both driven from the same PWM signal (i.e. when one sees 75% on, the other sees 75% off).

If it /is/ necessary to apply an offset then it might end up being best to manually code something in a timer interrupt handler, particularly since I am told that typical valves should operate at about 10Hz but not much faster: this eliminates most of the standard PWM libraries.

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


title: Buttons pressed in correct order

text:
# Question
Title: Buttons pressed in correct order
I’m trying to figure out the best way of doing this, currently using a bunch messy if-statements which kind of work. I have an IR sensor and three buttons that all need to be activated in the right order. Each sensor/button will activate LEDs and sound effects. First, when sensor1 goes HIGH, button1 can be pressed momentarily, then button2, then button3. If sensor1 is LOW, then nothing should happen when the buttons are pressed. When sensor1 is HIGH then the buttons should be pressed in the right order to progress through the sequence. When sensor1 goes back to LOW it should reset everything and allow the sequence to be run again when HIGH. Should I look into case switches for this?

Thank you

Jason

# Answer
This is a classic application for a state machine, in which you keep track of where your process currently is in the sequence of events that must take place. The 'state' is just a numeric variable whose value you change whenever a significant event takes place.

You would probably assign 0 - Initial state, waiting for an event (or the first event); 1 - Sensor is high, 2 - button-1 went high, 3 - button-1 went low; ... etc.

It always helps to sketch out your state machine on paper, drawing a circle for each state, and arrows from each state 'x' to whatever the next state should be if an event 'y' happens while in state 'x'. The events are sensors and buttons going HIGH or LOW. In a particular state, no arrow for some event means you want to ignore that event while you are in that state.

Once you have drawn the map you can code the state machine. A common way of coding it is with a `switch`-`case` block, one case per defined state. Inside each `case` block, you test only for those events for which there is an arrow leading from that state to another state.

As you add new conditions, (e.g. "What should happen if the sensor goes low after button-1 has been pressed?"), `switch`-`case` logic will be much easier to modify than if you had used a complex collection of `if`-`then` statements. And you *will* be adding new conditions & removing or fixing wrong ones as you discover ways the device fails or humans do things you didn't anticipate. (Ask me how I know this! :-)

It will be really helpful to be able to go back to your state map to visualize what should (or shouldn't) happen, and what to change (on the map) to make that behavior. From the updated map, it is usually easy to see what code needs to be added, deleted, or fixed in the `switch`-`case` block.
> 1 votes

---
Tags: programming
---


title: Connect OLED SSD1306 to Elegoo Uno R3

text:
# Question
Title: Connect OLED SSD1306 to Elegoo Uno R3
I'm trying to connect the OLED SSD1306 screen to my Elegoo Uno R3 and display something using Arduino IDE. However, nothing shows up on the screen for some reason.

I have connected every pin in the following way:

* VCC: 3.3V
* GND: GND
* SCL: A5
* SDA: A4

You can see the setup in the following pictures:

Then, I'm using the code from this tutorial, that is, this code, to see if the setup is correct, but nothing shows up on the screen. My question is: does anybody know if this is right way to do it? Even though I'm using analog pins and the screen needs digital ones, I read online that it doesn't matter:

> The analog input pins can be used as digital pins, referred to as A0, A1, etc. The exception is the Arduino Nano, Pro Mini, and Mini’s A6 and A7 pins, which can only be used as analog inputs.

I also saw in Elegoo Uno R3's guide that the A4 and A5 pins are used for the I2C protocol, which is the one that this OLED screen uses:

So as far as I know, from the hardware point of view, everything seems to be correct, right?

# Answer
You are close. Looks like you have a run-of-the-mill, clone \[not Adafruit\], 128x64 LCD with / I2C interface.

1. Determine the I2C address by flipping it over and seeing which side a 0 ohm resistor or solder blob is on - either 0 or 1. If it is on the '0' side, the address is 0x3C if it is on the '1' side, it is 0x3D.

Here is a photo of the back and with the address of 0x3c.

If the back of yours looks very different, locate and run an I2C device scanner to find the address of your display.

2. Do not use the code that you linked.

From the Arduino IDE, install or update the the Adafruit SSD1306 library, Version 2.57 is what I used to test this.

Once the library is in place, load the example SSD1306\_128X64\_I2C

Locate this line (near the beginning of the code):

#define SCREEN\_ADDRESS 0x3D ///\< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Change 0x3D to 0x3C if you need to (as determined earlier). I don't think it is an Adafruit screen, so you can ignore the comment.

3. Triple check your 4 connections

Run demo and audibly gasp - "cool".

PS: Mine works on either 3.3V or 5V
> 0 votes

---
Tags: arduino-uno, arduino-ide
---


# Question
Title: Changing Frequency of PWM Pin on Arduino Uno
I am trying to change the frequency of the PWM output from an Arduino Uno R3 (Been using Pin 9) to 200 Hz with a duty cycle of 20%. This is for an ESC that is connected to a 12V motor, and I know the ESC works as if I input a 200 HZ wave from a waveform generator the motor runs. However, I have been finding it difficult to do the same thing with an Arduino Uno and I believe it is due to the frequency being a default of 490 Hz, so I need a way to change that frequency to 200 Hz. Are there any libraries or specific ways to do so?

Thanks!

# Answer
> 2 votes
You can also use my newly-created **AVR\_PWM** library to shield you from dealing with complex hardware registers

For example

```
#include "AVR_PWM.h"

#if ( PWM_USING_ATMEGA2560 )
  // Pins tested OK in Mega
  //#define pinToUse      12            // Timer1B on Mega
  //#define pinToUse      11            // Timer1A on Mega
  //#define pinToUse       9            // Timer2B on Mega
  //#define pinToUse       2            // Timer3B on Mega
  //#define pinToUse       3            // Timer3C on Mega
  //#define pinToUse       5            // Timer3A on Mega
  //#define pinToUse       6            // Timer4A on Mega
  //#define pinToUse       7            // Timer4B on Mega
  #define pinToUse       8            // Timer4C on Mega
  //#define pinToUse      46            // Timer5A on Mega
  //#define pinToUse      45            // Timer5B on Mega
  //#define pinToUse      44            // Timer5C on Mega

#elif ( PWM_USING_ATMEGA_32U4  )
  // Pins tested OK on 32u4
  //#define pinToUse      5            // Timer3A on 32u4
  #define pinToUse      9            // Timer1A on 32u4
  //#define pinToUse      10            // Timer1B on 32u4

#else

  // Pins tested OK on Nano / UNO
  #define pinToUse      9            // Timer1A on UNO, Nano, etc
  //#define pinToUse     10            // Timer1B on UNO, Nano, etc
  //#define pinToUse      5               // Timer0B on UNO, Nano, e
  //#define pinToUse       3            // Timer2B on UNO, Nano, etc
#endif

//creates pwm instance
AVR_PWM* PWM_Instance;

float frequency;
float dutyCycle;

void setup()
{
  Serial.print(F("\nStarting PWM_Basic on "));
  Serial.println(BOARD_NAME);
  Serial.println(AVR_PWM_VERSION);

  //assigns PWM frequency of 200 Hz and a duty cycle of 0%
  PWM_Instance = new AVR_PWM(pinToUse, 200, 0);
}

void loop()
{
  frequency = 200;
  dutyCycle = 20;

  PWM_Instance->setPWM(pinToUse, frequency, dutyCycle);

  delay(10000);
  dutyCycle = 90;

  PWM_Instance->setPWM(pinToUse, frequency, dutyCycle);

  delay(10000);
}

```

# Answer
> 2 votes
If you are prepared to use Timer 2 (Pin D3) this code will do it:

```
void setup()
 {
  pinMode (3, OUTPUT);

  TCCR2A = bit (WGM20) | bit (WGM21) | bit (COM2B1); // fast PWM, clear OC2B on compare
  TCCR2B = bit (WGM22) | bit (CS20) | bit (CS21) | bit (CS22); // prescaler of 1024
  OCR2A =  77;    // zero relative
  OCR2B =  15;    // 20% duty cycle
  }  // end of setup

void loop()
  {
  // do other stuff here
  }

```

More information on the Atmega328P timers on my page about timers.

The figure 77 is obtained from:

```
16000000 / 1024 / 78 = 200.32

```

In other words, the prescaler of 1024 is divided into the clock of 16 MHz, and then we count up to 78, giving a result of just over 200. I actually use 77 because the timer is zero-relative (it counts from 0 to 77, giving 78 counts). This means the frequency is slightly out (it will be 200.32 Hz rather than 200 but that could be close enough).

---

You could also do it with Timer 1 (pin D10) to get slightly more accurate results, like this:

```
void setup()
 {
  pinMode (10, OUTPUT);

  // mode 15
  TCCR1A = bit (WGM10) | bit (WGM11) | bit (COM1B1); // fast PWM, clear OC1B on compare
  TCCR1B = bit (WGM12) | bit (WGM13) | bit (CS11);   // fast PWM, prescaler of 8
  OCR1A = 10000 - 1;   // what to count to
  OCR1B = 2000 - 1;    // duty cycle
  }  // end of setup

void loop()
  {
  // do other stuff here
  }

```

In this case I have used a prescaler of 8 and a count-up value of 10000, as follows:

```
16000000 / 8 / 10000 = 200

```

In this case the answer is exactly 200, which will be more accurate than the 200.32 obtained from using Timer 2. That is because Timer 1 is a 16-bit timer and has higher resolution.

---
Tags: arduino-uno, pwm, frequency
---


# Question
Title: Connecting the MKR GPS shield by cable or as a shield
I have an MKR WiFi 1010 and an MKR GPS Shield. When I connect my GPS Shield using the I2C cable, it works fine.

This works perfectly (the bottom is the MKR Motor Carrier):

However, when I use it as a shield (hat?) using the pins, it doesn't.

This doesn't work. The code blocks somewhere (I suspect `GPS.available()`):

My question, should it work the same whether it is cabled or put on with the pins? Or should I change my code somehow?

# Answer
From the shop page:

> It interfaces with Arduino boards either through a serial interface, when used with headers and put on top of a MKR board, or through an I2C interface and a dedicated ESLOV cable supplied as bundle.

From Arduino\_MKRGPS library reference:

`begin()` Parameters:

* GPS\_MODE\_I2C to use the MKR GPS with the I2C cable (default setting),
* GPS\_MODE\_SHIELD if using the MKR GPS as a shield.
> 1 votes

---
Tags: gps, mkr1010
---


# Question
Title: Arduino not recognizing external microcontroller
I've been trying to follow the official Arduino instructions on how to program and power an external breadboard, and I've gotten a pack of ATmega328p's that may or may not have been preloaded with the bootloader (found here). From the title, I assumed that they were, in fact, preloaded, but I followed the instructions to "reload it" from a working Arduino (with its original microcontroller), and I did it with the following circuit setup (this is the best image that I have of it, unfortunately, I promise I've checked that the wiring actually is equivalent to the original diagram, just shifted around for convenience on the breadboard):

I'm not sure whether I should've kept the original microcontroller in, as the guide ambiguously shows a void in the area where the controller should be in the provided diagram...

...but my thinking was that the Arduino basically isn't anything without its attached microcontroller, so attempting to "send" bootloader code to a separate microcontroller would require a plugged in microcontroller, and that was the only way I got it to work.

With all this set up, I tried to test using this new microcontroller, and it worked perfectly when mounted in the provided microcontroller area. However, when I tried to follow this up with the steps detailed in the guide, found here, with the following circuit (slightly better angle):

...I was faced with errors of being unable to connect.

From what I understand, it seems like the Arduino should automatically detect that no microcontroller is plugged in, hence allowing the stated "FTDI chip can talk to the microcontroller on the breadboard instead" from the guide. However, the error I'm getting seems to be the same as the error I got when I just plainly tried to send code or program without any microcontroller connected, so I'm assuming this implies that it can't find any microcontroller, either internal or standalone.

From googling this error, it seems that others have had this problem with seemingly no solution, and I have absolutely no idea how I could fix this. If there's something I'm missing, would greatly appreciate the help.

side note, when I was idly testing out the program with a tiny test circuit that lights up an LED, after programming it with a program that turns on a GPIO pin, connecting that pin to the LED, it did in fact light up. I'm concluding this means that the setup of the actual microcontroller is functional, but it's unable to be written to. this has also happened with the original microcontroller that I tried to simply program externally.

any help is appreciated, thanks for reading!

# Answer
> 1 votes
In the case of using an Arduino as a USB/UART (FTDI) adapter to upload a sketch onto a barebones Arduino (ATMEGA328P) via its own bootloader, a reset of that MCU chip must preceed the sketch upload. That is because, immediately following the reset, the bootloader watches the serial traffic to see if this is marked as a sketch upload and, if so, processes it. If this reset operation fails, for example through a bad or missing connection, the sketch upload attempt will also fail. A good description of the sketch upload process can be found here: https://www.instructables.com/Overview-the-Arduino-sketch-uploading-process-and-/

---
Tags: arduino-uno, breadboard
---


title: How to reduce codes numbers

text:
# Question
Title: How to reduce codes numbers
I am new in Arduino projects, i made a digital counter that counts from 00 to 99. Here is my code below

```
void setup()
{
pinMode(0,OUTPUT);
  pinMode(1,OUTPUT);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
}

void loop()
{
/* segment starts from 00*/
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,HIGH);
digitalWrite(0,LOW);
digitalWrite(3,LOW);
/* segment will now be 10, the 0 will continue counting up to 1*/

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(5,HIGH);
digitalWrite(4,LOW);
/* the segment will now be 20 */

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,HIGH);
digitalWrite(5,HIGH);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,LOW);
digitalWrite(6,HIGH);
digitalWrite(5,LOW);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,HIGH);
digitalWrite(6,HIGH);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(5,HIGH);
digitalWrite(4,LOW);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,HIGH);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,LOW);
digitalWrite(7,HIGH);
digitalWrite(6,LOW);
digitalWrite(5,LOW);

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,HIGH);
/* the segment will now be 9 0 */

digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(3,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(2,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(1,HIGH);
digitalWrite(0,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(3,HIGH);
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(2,LOW);
delay(500);
digitalWrite(0,HIGH);
delay(500);
digitalWrite(4,LOW);
digitalWrite(7,LOW);
/* when it gets here the segment resets to 00*/
}

```

It works pretty fine but the problem i have is the code is too long, is there a method i can use to reduce the length of the codes?

# Answer
> 3 votes
What you are writing here is some sort of binary counter: a BCD (binary-coded decimal) counter to be precise. It turns out that the processor inside the Arduino already works in binary. It's its native language, so you do not have to tell it how to do binary. You just have to know what operators to use in order to access the individual bits.

My approach would be to write a function that can display any number `n` between 0 and 99. The first step is to do the decimal decomposition: divide by 10, and take the quotient (first digit) and the remainder (second digit). These digits will be represented in binary within the machine. The next step is to access the individual bits. This is a two step process:

1. Shift the bits of the number to the right until the bit you want is at the far right. This is accomplished with the right-shift operator.
2. Compute the bitwise AND with the number 1 (0000000000000001 in binary). This will clear all the bits but the one you want, and result in either 0 (the same as `LOW`) or 1 (i.e. `HIGH`).

For example, if you want to get bit 1 of the number 7, you do

```
0000000000000111 = 7  initial number
0000000000000011 = 3  shifted one potion to the right
0000000000000001 = 1  bitwise AND-ed with 1

```

In code:

```
void display(int n)
{
    int digit0 = n % 10;
    int digit1 = n / 10;
    digitalWrite(0, (digit0 >> 0) & 1);
    digitalWrite(1, (digit0 >> 1) & 1);
    digitalWrite(2, (digit0 >> 2) & 1);
    digitalWrite(3, (digit0 >> 3) & 1);
    digitalWrite(4, (digit1 >> 0) & 1);
    digitalWrite(5, (digit1 >> 1) & 1);
    digitalWrite(6, (digit1 >> 2) & 1);
    digitalWrite(7, (digit1 >> 3) & 1);
}

```

**Edit**: If you need more that 2 digits, you have to successively divide by 10:

1. Divide the number to be displayed by 10: the rest of the division is the rightmost digit
2. replace the original number by the quotient of the division
3. divide again by 10: the rest of the division is the second rightmost digit
4. replace the original number by the quotient of the division
5. etc.

For example, for three decimal digits:

```
void display(int n)
{
    int digits[3];  // digits[0] is the rightmost digit
    digits[0] = n % 10;
    n /= 10;
    digits[1] = n % 10;
    n /= 10;
    digits[2] = n % 10;

    // Now make sure that n < 10 (otherwise we are missing digits),
    // then display digits[0], digits[1] and digits[2].
}

```

The main program now only has to loop through the numbers 0 to 99, and display each one in turn:

```
void loop()
{
    for (int n = 0; n < 100; n++) {
        display(n);
        delay(500);
    }
}

```

# Answer
> 1 votes
I suggest you look up how to do loops in a C or C++ programming tutorial. For example you can replace:

```
void setup()
{
  pinMode(0,OUTPUT);
  pinMode(1,OUTPUT);
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
}

```

with:

```
void setup()
{
  for (int i = 0; i <= 9; i++)
    pinMode(i,OUTPUT);
}

```

---
Tags: arduino-uno, arduino-ide
---


# Question
Title: The same button with one click and double click
i hope to get some help with my code.

I am trying to distinguish between a single press and a quick double press of the button with debouncing.

I am making some silly mistake in my code and i can't find out the problem. If I double press the button, both 'single' and 'double' gets printed on the serial monitor.

Thanks in advance for some help.

```
const int buttonPin = 5;
unsigned long lastPressTime;
int buttonState = 0;
int singlePress = 0;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  lastPressTime = millis();
  Serial.begin(9600);
}

void loop() {
  if (!digitalRead(buttonPin) == HIGH && buttonState == 0) {
    unsigned long currentPressTime = millis();

    //two presses within 500ms
    if (currentPressTime - lastPressTime < 500) {
      singlePress = 0;
      //Do double press action
      Serial.println("double");
    } else {
      singlePress = 1;
    }

    //update the last pressed time
    lastPressTime = currentPressTime;
    buttonState = 1;
  } else if (!digitalRead(buttonPin) == LOW) {
    buttonState = 0;
  }

  //check if 500ms have passed with no second button press
  if (singlePress == 1 && lastPressTime  - millis() > 500) {
    singlePress = 0;
    //DO single press stuff
    Serial.println("single");
  }
}

```

# Answer
> 1 votes
The problem is this statement:

```
lastPressTime  - millis() > 500

```

Because time is stored as an unsigned long, this test as it is written now is always true.

You want to measure the time since the last press, so you should subtract the timestamp of the last press from the current time. Replace it with:

```
millis() - lastPressTime > 500

```

And the code will run fine.

# Answer
> 0 votes
Thank you all for your help...

Definitely the problem in my code, to get the one click and double click working like @mhopeng wrote, was this statement:

```
lastPressTime  - millis() > 500

```

changing it to this

```
millis() - lastPressTime > 500

```

maked it work.

But what i realize is that my approach is not enough responsive. Using the approach of @6v6gt is much better than mine. The reaction is much more responsive and smoother.

```
// note the simulation speed is about one third of real time
// adjust timings if using on real hardware.

const int buttonPin = 5;
unsigned long inStateAtMs = millis() ;
int buttonState ;  // 0 = waiting for press, 1= waiting for release 2= differentiate single or double 3= wait button release (double)

void setup() {
 pinMode(buttonPin, INPUT_PULLUP);
 Serial.begin(9600);
}

void loop() {

 if ( buttonState == 0 ) {
   // wait for button press
   if ( millis() - inStateAtMs > 100 ) {
     if (!digitalRead(buttonPin)) {
       buttonState = 1 ;
       inStateAtMs = millis();
     }
   }
 }
 else if ( buttonState == 1 ) {
   // wait for stable button release 1
   if ( millis() - inStateAtMs > 100 && digitalRead(buttonPin) ) {
     buttonState = 2 ;
     inStateAtMs = millis();
   }
 }
 else if ( buttonState == 2 ) {
   // differentiate between single and double press
   if ( millis() - inStateAtMs > 400 ) {
     // timeout - is a single press
     Serial.println("single");
     buttonState = 0 ;
     inStateAtMs = millis() ;
   }
   else if (  ( ! digitalRead(buttonPin) ) && (millis() - inStateAtMs > 100 ) ) {
     // got second press within timeout - double
     Serial.println("double");
     buttonState = 3 ;
     inStateAtMs = millis() ;
   }
 }
 else if ( buttonState == 3 ) {
   // wait for stable button release 2
   if ( millis() - inStateAtMs > 100 && digitalRead(buttonPin) ) {
     buttonState = 0 ;
     inStateAtMs = millis();
   }
 }
}

```

Thanks again all of you for the help

---
Tags: arduino-uno, programming, button, millis
---


# Question
Title: How to find the correct navigation course by gps navigation with Arduino?
I have a problem for about days ago and here it is :

I have an RC plane and wanna make it autonomous via GPS navigation by Arduino

I have an Arduino Mage 2560 onboard connected to a GPS Ublox-Neo-M8N (GPS module) and there is the problem

I want my RC-Plane to read it's position and go to waypoints

The Coordinates of two waypoints are defined before on a matrix variable like this example :

```
a [1] [3] =
{
    {38.884675, -116.671035,
     245}
};

b [1] [3] =
{
    {38.725019, -116.580951,
     1180}
};

( 1st is Latitude, 2nd is Longitude and 3rd is height)

```

So i want my Arduino to read it's current position from gps module's data and calculate the correct Azimuth (correct horizontal angle) and the correct pitch angle (vertical angle) to navigate my plane to the waypoints

and remember, when it reaches to the waypoint "a" with a few error (miss distance = 4 meters), it should be able to ignore navigation to the waypoint of variable "a" and then, navigate to waypoint "b"

I WAND THE EXACT COMMAND FROM ANY LIBRARY TO CALCULATE THOSE TWO ANGLE FOR NAVIGATION (azimuth direction angle and pitch angle to navigate RC-Plane from everywhere o the waypoints

# Answer
The computation is not difficult. Since your drone is unlikely to travel for thousands of kilometers, you can assume the Earth is locally flat, and the latitude and longitude are an orthogonal coordinate system. First, compute the vector to the next waypoint in Cartesian coordinates (dx, dy, dz):

```
// Defined at global scope.
const float radians_per_degree = M_PI / 180;
const float degrees_per_radians = 180 / M_PI;
const float meters_per_degree = 1e7 / 90;

// For every reading of the GPS:
float dx = (waypoint.longitude - current.longitude) * meters_per_degree
         * cos(current.latitude * radians_per_degree);
float dy = (waypoint.latitude - current.latitude) * meters_per_degree;
float dz = waypoint.height - current.height;

```

Then, from this vector you can get the required angles:

```
float azimuth = atan2(dx, dy) * degrees_per_radians;
float pitch_angle = atan(dz/sqrt(dx*dx + dy*dy)) * degrees_per_radians;

```

Note that the approximation breaks down if the drone has to travel for a distance that is a significant fraction of the distance to the closest pole. Note also that the approximation errors are inconsequential if you periodically update your estimate of azimuth and pitch angle: the errors will be corrected along the way as the drone gets closer and closer to the waypoint.

**Edit**: timemage posted a very interesting comment, and I would want to further expand on the precision issue. The AVR floating point support is indeed limited to single precision. For latitudes and longitudes in the range shown in the question, the numerical resolution (formally, the unit in the last place) is (3.81×10−6)° for the latitude and (7.63×10−6)° for the longitude. This translates to about 42 cm and 66 cm respectively on the surface of the Earth. It may be just good enough to hit the waypoint to within 4 m.

You could increase the resolution by storing the latitude and longitude in microdegrees, as 32-bit integers. This should be easy if the GPS always gives 6 digits after the decimal point: just ignore that decimal point. Then, once the quantities `waypoint.longitude - current.longitude` and `waypoint.latitude - current.latitude` are computed, you can safely use floating point for the rest of the computations.
> 4 votes

---
Tags: arduino-mega, gps
---