# Question
Title: Where does this sketch have Undefined Behavior?
Simple sketch and simple question: where does this sketch have undefined behavior?

Note: I don't need a solution to fix the code. I already have code that works. I really need to understand where my thinking is wrong.

Background: some kids were writing a program for a line follower robot which has 3 digital sensors. Many of them bricked their Arduino. I reduced the affected sketches to quite a minimum so that it still reproduces the problem. The sketch is pretty self-explanatory I hope.

It gives no warnings in Arduino IDE 1.8.9, 1.8.15 and 2.0.4 even with all warnings enabled.

Still, this code bricks all the Arduino clones (9 instances of Elegoo Smart Robot Car Kit 3.0 Plus) and I spent several hours to find a reliable procedure to unbrick them. Therefore I have strong belief that this code must have undefined behavior - except that I can't see it.

The unbrick procedure is:

1. Remove the shield, if not removed yet
2. Disconnect Arduino from USB
3. Connect Arduino to USB
4. Press Reset button on the Arduino board
5. Disconnect Arduino from USB again (!)
6. Connect Arduino to USB
7. Compile and upload an empty sketch

```
long PIN_LINE_LEFT = 10;
long PIN_LINE_MID = 4;
long PIN_LINE_RIGHT = 2;
long DATARATE = 115200;

void setup() {
  pinMode(PIN_LINE_LEFT, INPUT);
  pinMode(PIN_LINE_MID, INPUT);
  pinMode(PIN_LINE_RIGHT, INPUT);
  Serial.begin(DATARATE);
}

void loop() {
  byte leftValue = digitalRead(PIN_LINE_LEFT);
  Serial.println(leftValue);
}

```

Here's my analysis:

IMHO, the sketch is unusual just in one way: instead of `#define`ing the pin numbers and other stuff, it declares them as global variables of type `long`.

According to the Arduino reference about data types a `long` is 32 bit. Printing `sizeof(long)` confirms that. Therefore, 115200 will not overflow at 65536 (16 Bit).

For `Serial.begin()`, the `DATARATE` will be converted into an `unsigned long`, which IMHO should not be a problem here, since the number is positive.

Sure enough, the pin numbers needn't be `long` and should be declared as `uint8_t` to better match the `pinMode()` and `digitalRead()` function. But I still think the implicit conversion down to `uint8_t` should be fine, since there is no overflow either.

Next, `digitalRead()` officially returns an `int`. The result is assigned to a `byte` which is an alias for `uint8_t`. It seems that this also gets converted implicitly. However, the values should only be `HIGH` or `LOW`, i.e. 1 or 0, which does not generate a signed overflow either.

What I tried:

Changing `DATARATE` to the more appropriate `unsigned long DATARATE = 115200UL;` doesn't change anything.

Changing `byte leftValue = digitalRead(PIN_LINE_LEFT);` to the more appropriate `int leftValue = digitalRead(PIN_LINE_LEFT);` also didn't change anything.

Changing `long PIN_LINE_MID = 4;` and all others to the more appropriate `uint8_t PIN_LINE_xxx = xxx;` also doesn't change anything.

IMHO with these changes, there's basically nothing left to fix and this should be a super valid C/C++ program without any implicit dangerous casts.

A `Serial.flush();` in the loop is not needed according to the documentation of `Serial.write()`. So there will not be a buffer overflow.

# Answer
> 2 votes
Your sketch does not have undefined behaviour. It works:

> I already have code that works.

Your problem apparently is that after loading this sketch you have trouble uploading a new sketch:

> this code bricks all the Arduino clones

They aren't "bricked" as you say:

> But your method works in ~9 out of 10 cases. I can't believe this.

Your sketch, which outputs repeatedly to the serial port, apparently makes it hard for a **clone** to respond to a new upload. The cheaper USB interface which the clones use, to save a few cents, evidently don't react as well as the genuine Arduino to attempts to upload a new sketch.

The suggested method in the comments (referencing my post Have I bricked my Arduino Uno? Problems with uploading to board) indicates the solution, and I quote:

> Take these steps:
>
> * Power off the board completely (remove the USB cable).
> * Hold down the Reset button, and keep it held down (or, run a jumper wire from the RESET pin to the GND pin). This stops the problem sketch from starting, and thus activating the watchdog timer
> * Still holding down Reset, reconnect the USB cable.
> * Start uploading a sketch that does not have this problem (eg. Blink)
> * Once the IDE reports "Uploading" release the Reset button (or remove the jumper wire).
> * It should now upload OK - as the sketch which activated the watchdog timer never started.

The solution above is to not let the current sketch run at all, thus avoiding whatever-it-is that it does to stop new sketches from uploading.

*The references to the watchdog timer are from the original post, they are not relevant here.*

---

> It gives no warnings in Arduino IDE 1.8.9, 1.8.15 and 2.0.4 even with all warnings enabled.

That's because there are no problems with the sketch per se. The hardware? Well, you buy cheaper hardware, you may get some problems. The technique described above helps you work around those problems.

# Answer
> 2 votes
With some USB to TTL Serial chips it is a problem to start the upload if there is too much input from the MCU on the Serial side. In this case it is the Holtek UART Bridge which is not common for Arduino boards.

To stop the sketch, hold the reset button until the upload from IDE starts. When the reset button is released, the bootloader starts and receives the upload.

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


# Question
Title: Arduino IDE. How do I use labels in a macro?
It's the Arduino Uno. I've spent hours reading on the internet but found nothing yet. If you use a label in the macro, the 2nd time it's called you get a duplicate label error.

# Answer
Just to make the question clearer, let's take a simple example. Consider the following assembly macro that implements a delay loop:

```
.macro short_delay
    clr  r0
repeat:
    dec  r0
    brne repeat
.endm

```

and use it in a program that repeatedly blinks the built-in LED of an Arduino Uno (a faster version of “Blink”):

```
main:
    sbi  DDRB, PB5   ; set pin 13 = PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    short_delay
    cbi  PORTB, PB5  ; turn PB5 LOW
    short_delay
    rjmp loop

```

When the assembler expands the macro, it ends up with this:

```
main:
    sbi  DDRB, PB5   ; set PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    cbi  PORTB, PB5  ; turn PB5 LOW
    ; start of short_delay macro
    clr  r0
repeat:
    dec  r0
    brne repeat
    ; end of short_delay macro
    rjmp loop

```

and this fails with

```
Error: symbol `repeat' is already defined

```

The solution to this problem is to use, inside the macro, only local labels. These labels are just numbers. When using them, one has to append the suffix “b” (for backwards) or “f” (forwards) depending on whether the label is defined before or after the point where it is being referenced.

The nice thing about local labels is that they are... well... local, and thus they can be safely reused many times. The assembler disambiguates them by choosing the definition that is *closer* to the point of use, along the specified direction. With a local label (I choose `0`), the delay macro becomes:

```
.macro short_delay
    clr  r0
0:  dec  r0
    brne 0b  ; the branch target is the preceding label `0'
.endm

```

When the macro is expanded, the main program becomes:

```
main:
    sbi  DDRB, PB5   ; set PB5 as output
loop:
    sbi  PORTB, PB5  ; turn PB5 HIGH
    clr  r0
0:  dec  r0
    brne 0b
    cbi  PORTB, PB5  ; turn PB5 LOW
    clr  r0
0:  dec  r0
    brne 0b
    rjmp loop

```

Although repeated, the label is not ambiguous, as `brne 0b` always refers to the *closest* label `0` along the **b**ackwards direction.
> 2 votes

# Answer
Welcome, this is the same thing I had problems a few years back. Define the label in the `macro` (function) and it will be local and not available to the rest of the world. You can use the same label as many times as you want they just need to be inside a `macro`.

```
void macro(int label)
{
   Do something with label and then exit;
}

```

You can do whatever you want, say get the value of several pins to see if they are all on then use the return true or false. When you leave the macro all of the variables will be lost and the memory returned to the heap. This is done in several ways in many of the libraries.
> -1 votes

---
Tags: assembly
---


# Question
Title: How does Arduino IDE reset a board before flashing? Why doesn't avrdude do it?
I have the beetle board, a Leonardo clone same as in this question.

Using the reset pin and quick hands on the keyboard, I am able to flash with avrdude and get also the board info with a command line like this:

```
$ avrdude -c avr109 -p atmega32u4 -P /dev/ttyACM1

```

And get the output:

```
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)

avrdude: safemode: Fuses OK (E:CB, H:D8, L:FF)

avrdude done.  Thank you.

```

This is good but when I flash something from the ArduinoIDE I noticed I don't have to reset the board manually by grounding the reset pins, the boot loader starts automatically

How does ArduinoIDE reset the bootloader, some kind of communication on `/dev/ttyACM1`?

# Answer
The uploaded Arduino sketch has in the part provided by core a code which waits for a 1200 baud connection on USB. If a 1200 baud connection is established it resets the board to bootloader. The bootloader then starts the com port and waits for the upload.

To reset a board which has in boards.txt `upload.use_1200bps_touch=true` Arduino IDE opens a 1200 baud connection to the board, then detects the new com port and start avrdude for the upload.
> 1 votes

---
Tags: arduino-ide, avrdude, atmega32u4
---


# Question
Title: Arduino IDE 1 interfering with Arduino IDE 2?
In our electronics tinker club, we had installed Arduino IDE 1.8 including drivers + the Holtek UART bridge (vendor ID 04D9, product ID B534) for the Elegoo Smart Car Kit 3.0 Plus (product link). The board is an Arduino Uno clone.

We now installed Arduino IDE 2.0.3 in parallel and tried that one, because its features looked promising.

However, in Arduino IDE 2.0.3, we had problems uploading the compiled sketch to the Smart Car Board. When I checked, it reported a different vendor ID and product ID (sorry, I didn't record which one).

I reinstalled the Holtek UART bridge driver (direct download executable) and tried again. The vendor ID and product ID were correct this time, but uploading was still not going well in Arduino IDE 2.0.3.

Switching back to Arduino IDE 1.8 doesn't help. While the code still compiles (I expected it to), the upload problems now affect Arduino 1.8 as well, which was totally fine before we installed Arduino IDE 2.0.3.

How could I fix this issue?

I'll try to uninstall and reinstall everything, but I'm not sure it will be possible to uninstall all drivers.

# Answer
> 2 votes
I spent more time (almost 20 working hours) to isolate this problem by

* testing the behavior with all of our 9 robot hardware in the club
* testing the behavior with all of our 8 notebooks in the club
* testing with the 6 different implementations we had, bricking and not bricking our robot hardware
* testing with an additional notebook that didn't seem affected
* combinations thereof

Finally I had a reproducible procedure with which I could "brick" a robot hardware and another procedure which would "unbrick" it.

That way I was able to a) minimize the code that was needed to "brick" the robot and b) compare that to the other codes that didn't have the issue. Finally I could ask this new question and get valuable feedback.

It turned out that this was **not related to the new Arduino 2.0.3 or 2.0.4 IDE. It was just a timely coincidence** that we wrote a new sketch we never wrote before in this way for this hardware.

That code used `Serial.begin()` with a "high" baud rate and obviously less delays than we ever used on this hardware before. And it turned out our hardware can't handle speeds higher than 19200 baud (!) without `delay()` statements. That's so slow!

---
Tags: arduino-ide
---


# Question
Title: Curious Collision between OneWire and RadioHead
The code below runs on an Arduino Pro Mini (8MHz 328p) sending temperature readings using an inexpensive ASK transmitter. I use OneWire to read the DS18B20s, and RadioHead to manage the radio.

The original problem was the send() calls at the top of the loop *always* worked, but the send() call in the temperature-reading loop *never* did.

The fix was to insert a call to setModeTx() ahead of the send() call. I'm pleased it works, but it's a hollow victory because I can't figure out *why* it works.

OneWire uses no timers and no interrupts. I wait for the temperature conversion using `_delay_ms()` which is a spin delay.

I've read and re-read the OneWire and RH\_ASK code and am still puzzled. Can anyone explain?

Many thanks

Here's the gist of the code…

```
RH_ASK radio(1024, 0, 10, 0, false);
OneWire ow(2);

void loop()
{
    radio.send(/* build info */);     // always works
    radio.send(/* battery health */); // always works
    ow.reset_search();
    while (ow.search(addr))
    {
        read_thermometer(addr);

        // the following send() works ONLY
        // when preceded by setModeTx()
        // It *never* works without it
        radio.setModeTx();
        radio.send(/* one temp reading */);
    }
}

```

UPDATE

@timemage was correct in that there are also calls to Serial (which resolve to HardwareSerial) interspersed. I'm no closer to solving it; however, by rearranging calls I can get the failure to happen more- or less often.

In a way this highlights the distinction between diagnosis and repair. I may in the end discover an ordering of the calls that makes the failure exceedingly rare, and in this case the problem will have been *repaired*; though not *diagnosed*.

# Answer
Finally had time to get back to this. I connected the data-out line from the sender to the data-in line of the receiver, and discovered it always works. So it's **not** any sort of collision between OneWire and RadioHead, curious or otherwise. There's something amiss with the radio link… but what?

Have a look at the following oscilloscope traces. The magenta line is the input to the transmitter. Cyan is the output from the receiver (an SYN480R if you're curious). Yellow is just there to trigger the scope (a digitalWrite() just before sending the problem message).

The packet from the transmitter begins with a series of training pulses for the receiver to establish things like gain and threshold for the demodulator. Thereafter, the data is encoded in a series of long and short pulses.

Note how the receiver (cyan line) syncs up with the training pulses, and is in lock-step with the transmitter... until ... IT GETS LOST and thinks everything is a zero for awhile. It eventually re-syncs with the transmitter, but by this point the packet is corrupt, gets rejected by the decoder, and *that* is why I'm losing the packet at the receiver.

But, one wonders, why this particular packet and not any of the others? The answer to that question is pretty much out of band for a software forum, but here goes. Let's add a trace to the scope display.

The following image includes the demodulator threshold in blue. That's an analog value that the demodulator uses to decide if it's looking at a one or a zero. For the SYN480R chip, it's the output of a low pass filter, which produces an *average* over the recent bits.

In this case, notice how the threshold rises during the early part of the packet, then settles down. My conjecture is there are too many ones in the packet encoding thus far (i.e. many more ones than zeroes), and this shifts the threshold high enough that the demodulator thinks everything it sees is a zero. This is confirmed in the previous image. Seeing all zeroes, the threshold settles down and the demodulator can sync up again.

Interestingly, just touching the scope probe to the threshold capacitor (to get the blue trace) disturbs the threshold enough to slow the rise and keep the packets working.

Thus, OneWire is definitely off the hook, as is any interaction with RadioHead. Moving on, I either need to make some tweaks to the RadioHead RH\_ASK driver packet encoder, or change out the threshold capacitor in the receiver. That in itself is a balance, because you want it to be able to track changes in the received signal, yet not be so sensitive to packet encoding.

Hope you found this interesting. Many thanks to everyone who took a look and offered your insight.
> 1 votes

---
Tags: arduino-uno, serial, atmega328, 1-wire
---


# Question
Title: Stepper motor micros (millis) non-blocking delay simple example?
I am trying to get a simple non-blocking replacement for:

```
digitalWrite(stepPinX, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinX, LOW);
delayMicroseconds(500);

```

This is what I tried, and the stepper motor stays still:

```
const int dirPinX = 0;
const int stepPinX = 2;

unsigned long startMicros = micros();
unsigned long currentMicros;
const unsigned long period = 500;

void setup()
{
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);

  digitalWrite(dirPinX, HIGH);
}

void loop()
{
  stepX();
}

void stepX()
{
  currentMicros = micros();  //get the current "time" (time since program start)

  if (currentMicros - startMicros >= period)  //test whether period elapsed
  {
    digitalWrite(stepPinX, HIGH);
  }
  if ((currentMicros - startMicros >= period) && (currentMicros - startMicros <= period*2))
  {
    digitalWrite(stepPinX, LOW);
  }

  startMicros = currentMicros;
}

```

Any suggestions on how to correct this? (I do not want to use a library like Accelstepper. I want to use millis/micros.)

# Answer
> 1 votes
Your `stepX()` function looks like this:

```
void stepX()
{
  currentMicros = micros();
  // conditionally do some stuff..
  startMicros = currentMicros;
}

```

Since there is nothing that can block it, it will always execute very fast. This means that, by the time the function returns, `startMicros` will be very close to the current time. Then, on the following call, `currentMicros - startMicros` will be very small, way smaller than `period`, and the conditional code will never execute.

The solution is to change the meaning of `startMicros`: instead of representing the time of the last call to `stepX()`, let it represent the time when the last step started. For this, you have to reset it only when finishing a step:

```
void stepX()
{
  currentMicros = micros();
  if (currentMicros - startMicros < period) {           // 1st phase
    digitalWrite(stepPinX, HIGH);
  } else if (currentMicros - startMicros < 2*period) {  // 2nd phase
    digitalWrite(stepPinX, LOW);
  } else {                                              // complete cycle
    startMicros = currentMicros;
  }
}

```

# Answer
> 1 votes
Looks like `startMicros` and `currentMicros` values always stay close to each other because of using `micros()` before and after the conditional block. Since the conditional block executes faster than 500 micros, resulting in never entering the conditional block.

From here you can take two approaches,

* **Approach 01:** Play with your code variables and debug in realtime to see what's wrong and where. Then tweak,debug, repeat until you reach the desired result
* **Approach 02:** Rethink w.r.t the code execution and simplify your code right from entry to exit in sequential steps.

Since your action can be simplified to a toggle operation every `500 microseconds`, we can refactor code similar to what I have written,

```
bool toggle_flag = false;
unsigned long last_toggle;
const unsigned long period = 500;

void setup() {
    last_toggle = micros();
    pinMode(stepPinX, OUTPUT);
}

void loop() {
  // Check to see if time elapsed
  if (micros() - last_toggle >= period ) {

      // Step 01: reset the last_toggle with current time
      last_toggle = micros();

      // Step 02: check toggle flag and perform the toggle action
      (toggle_flag) ? digitalWrite(stepPinX, HIGH) : digitalWrite(stepPinX, LOW);

      // Step 03: toggle the toggle flag variable after our action
      toggle_flag = !toggle_flag;

  }

}

```

Hope this answer helps.

---
Tags: millis, stepper-motor
---


# Question
Title: What is the best way to create a library from existing functions?
I was tasked to take functions that work, and create a library with these functions.

Take a look at the following function that existed inside a program:

```
char* Num_to_HEX_char_array(int32_t value)
{
  Clear_array(MyTempArray, MY_TEMP_ARRAY_LENGTH);
  ltoa(value, MyTempArray, HEX);
  return MyTempArray;
}

```

(Let's ignore the fact that this function) This cannot be immediately made into a library, as `MyTempArray` is non existant. This, in the `.cpp` file, i will have to manually create these lines:

```
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];

```

Now the library compiles fine. However, this library can be called by many programs that I create, and some of them might require a different array length, while others ay require a different name than this one.

So what is the best way to create this library?

\*One approach that I thought was to dynamically create these arrays with `malloc()`. And then, on the main program, you will have to `realloc()` the arrays with the ones you want. Also, use `undef` and re`#define`. The drawbacks to this approach is that you have to remember to ALWAYS use these statements, if you want your library to work

\*Another approach is to place all this code:

```
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];

```

inside a configuration header file. The variables will be of global scope. Then, when you create an application, you will only have to change this file.

My question to this approach is How exactly can you make sure that this configuration file is read by all the libraries?

Maybe you many libraries, for example, string-handling, or sensor-handling... Each and every one of these user-created libraries have to `#include` and see that configuration header file, in order to make sure that the definitions and arrays of correct/name and size. How can you do this so that it is visible by all your user-created libraries? Where is the optimal location to place that file?

In general, what is the best approach to solve this issue?

# Answer
I'd write such a function to expect the calling function to allocate the array and pass it and its size as arguments. That leaves the memory allocation and deallocation up to each library user, who may want/need (for other reasons) to use a static array, heap memory, or an automatic array and allows them to de-allocate it (or not) when their application no longer needs it. Coding these details into your library would restrict its usability.
> 2 votes

# Answer
First of all, I must say I have an issue with the example you provide. The function `Num_to_HEX_char_array()` should use an array that has the maximum size that `ltoa()` may ever need. No more, no less. There is no point in letting the user of the library choose this size. Here is how I would implement this function:

```
char *Num_to_HEX_char_array(int32_t value)
{
    static char buffer[2 * sizeof(long) + 1];
    return ltoa(value, buffer, HEX);
}

```

That being said, I am willing to accept the idea that your library has some static buffers for which it does make sense to let the user choose the size. You could probably find a better example to put in the question though.

In this case, I would suggest you first consider the approach proposed by JRobert, and let the user provide those buffers. Using static buffers in a library can make the API easier to use in the most common cases. There are many function in the C standard library that do this, like, e.g. `ctime()`. This, however, comes at a cost:

* the user must be well aware that calls to the library can clobber data returned by previous calls
* the functions are not re-entrant, meaning they cannot be used in multiple threads, and they cannot be used both in interrupt and non-interrupt contexts.

This is why you have functions such as `ctime_r()`: to provide an alternative that lets the user handle the buffer, and does not suffer from the previous shortcomings.

If you still believe you want static buffers inside your library, then you should first consider whether it is possible to fix the size, like in the `Num_to_HEX_char_array()` example. If this is not possible, then the best I can think of is to use C++ templates. For example:

```
template<size_t size> class CircularBuffer {
    int buffer[size];
    // ...
};

```

which would be instantiated like this:

```
// Let `queue' be a 42-slot circular buffer.
CircularBuffer<42> queue;

```

Keep in mind, though, that this technique forces you to put most of the code in the header file.
> 2 votes

# Answer
Command line compilers and most IDEs for C and C++ enable to set project defines as -D parameters in project settings. Arduino IDE does not enable this yet, because it doesn't have a project configuration file.

With Arduino IDE you can add defines for platform or for board definitions with build.extra\_flags in platform.local.txt or in boards.local.txt. Example for boards.local.txt for Arduino Mega:

`mega.build.extra_flags=-DUIP_CONF_UDP_CONNS=20 -DUIP_CONF_MAX_LISTENPORTS=30`

platform.local.txt and boards.local.txt must be in boards package folder nect to platform.txt and boards.txt.
> 1 votes

---
Tags: library, array
---


# Question
Title: ESP8266 - error after board update to 3.1.1
I'm using a Ubuntu 22.04 and Arduino IDE 1.8.19 for my ESP8266 Projects.

Yesterday I upgraded to 3.1.1 (using board library manager), and right after that - I got the following message (few seconds after compilation start):

```
Traceback (most recent call last):
  File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 846, in <module>
    sys.exit(main())
  File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 759, in main
    if time.time_ns() < os.stat(commonhfile_fqfn).st_mtime_ns:
AttributeError: module 'time' has no attribute 'time_ns'
exit status 1
Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

```

Steps done to find the reason:

1. Empty Sketch - occurs.
2. Any other ESP8266 board - occurs.
3. Going back to prior version, 3.1.0 - occurs.
4. Going back to 3.0.2 - OK!
5. Checking 3.1.1 on Mac, same IDE version - OK!

Any ideas why ? Am I the only one ?

Guy

# Answer
The error tells you, that the time.time\_ns() python function does not exist. This function was added to the python time lib with Python3 version 3.7.

The most likely scenario I can imagin here is, that a python 3.6 or lower version is installed on your ubuntu and therefore the board software does not find the required function.

Depending on how the ARDUINO IDE is configured, the globally installed python or a special installation of python is used. We dicussed these two possibilities in the chat and realized that in your case, snap installs its own dependency of python. I assume that the version of this python was below 3.7 and therefore the plugin was unable to find the required time function.

If the Arduino IDe would have been depent on the global python installation, it would have been enough to install a newer python (e.g. 3.10+) globally.

In you case (dependency defined by snap), the only solution I have, is to install the IDE not with snap but with the manual installation or by using apt. There are instruction in the internet like https://www.computingpost.com/how-to-install-arduino-ide-on-ubuntu-22-04-lts/.

Please check the comment of @userfuser (about usíng an .AppImage file) in the dicussion below the question also.
> 1 votes

---
Tags: esp8266, core-libraries
---


# Question
Title: Controlling a servo without the servo library
I am trying to control a servo without the "Servo.h" library.I am sending using `analogWrite()` some values to the servo.I know the servo takes input a continuous time signal however I dont know the necessary frequency of that signal so I am not producing any sensible movement.What else should I consider when trying to control the servo using `analogWrite()`s?

# Answer
It can be done using `digitalWrite()` and `delayMicroseconds()`.

A servo is driven by a pulse. The pulse is between 1 ms (0°) over 1.5 ms (90°) to 2 ms (180°), followed by a pause that makes the total duration of a cycle 20 ms.

The 20 ms correspond to a 50 Hz signal. `analogWrite()` uses frequencies from 490 to 1000 Hz (depending on your hardware), which is why that won't work unless you figure out how to change the frequency.
> 0 votes

---
Tags: servo, pwm, analog
---


title: Checking a thing about interrupts

text:
# Question
Title: Checking a thing about interrupts
If I disable interrupts (for example `noInterrupts` or `cli`) and enable them (`interrupts` or `sei` for example) later, would interrupts which would have executed in the window in between fire by the execution of the latter? I guess not, and haven't confirmed or denied it. If not it is always an option to manually disable timers or components with similar concerns with respect to the interrupt status? It makes sense that AVR-based Arduino boards would behave similarly. It seems plausible that the bits for the force interrupt execution will turn on and turned off when the jump occurs. Thanks for reaching out.

# Answer
> 3 votes
See How do interrupts work on the Arduino Uno and similar boards?

Yes, most interrupts will be remembered and the ISR will be executed when interrupts are enabled again, plus one more instruction has been executed. If that didn't happen it would be very bad, as you may turn off interrupts briefly and you wouldn't want to miss the thing that the interrupt was for (eg. incoming serial data).

To stop that happening you need to clear the "interrupt has happened" bit for the individual interrupts. This is documented in the datasheet for each interrupt.

The order in which outstanding interrupts will be serviced is the interrupt priority, that is lower-numbered interrupts will be serviced first. The call to the ISR causes the processor to clear the "interrupt has happened" bit for that interrupt.

---
Tags: arduino-uno, arduino-nano, interrupt, avr
---


title: AA alkaline batteries on firebeetle?

text:
# Question
Title: AA alkaline batteries on firebeetle?
I would like to power a dfrobot firebeetle 2 using 3 alkaline batteries. I tried connecting the battery pack to the GND and VCC, but the board does not seem to react. What pins should i connect the leads to?

The firebeetle 2 info page: https://www.dfrobot.com/product-2195.html

# Answer
The following is based purely on the small amount of information in your question. You haven't described your code or your setup, which would allow this answer to be more specific.

According to the FireBeetle ESP32 schematics here, you should be able to connect an external power supply between VCC(+) and GND(-).

The voltage regulator on the FireBeetle ESP32 is a low-dropout RT9080 regulator, which, according to its datasheet has a maximum voltage drop of about 0.5 V when outputting the 3.3 V needed by your board and a maximum input voltage of 5.5 V.

That means the voltage supplied at VCC should be between 3.8 V and 5.5 V, and the ~4.5 V supplied by your 3 x AA batteries (assuming they're connected in series), falls nicely into this range.

The fact that your board does not seem to run your code might be caused by a number of things.

1. Does your program expect a Serial port connection which, of course, is not available when it's not connected to a PC by USB?
2. The power demanded by your board might be too high for the batteries. Are there other things connected to the board that that could cause that?

If you have a multimeter, you should be able to measure a stable 3.3 V on the 3.3 V pin of the FireBeetle.
> 2 votes

---
Tags: power, esp32, battery
---


# Question
Title: Is there an Apple Silicon (M1) driver for CH34x devices?
I just migrated to a new computer running on an M1 CPU (the new Apple Silicon, arm64 based). I've been searching for CH34x drivers for my TTGO-Lora32 board, but can't find any around, nor can I find mentions of them existing or not. The x86\_64 driver installs, but obviously can't run due to it being an incompatible architecture.

Thus, is it currently possible to use a CH34x based board on an M1 Mac?

# Answer
> 4 votes
As it turns out, I found in the following post:

https://github.com/LilyGO/LILYGO-T-OI/issues/3#issuecomment-907645945

a link to a particular build of the CH340 drivers that is properly signed and can be installed on the M1 mac with no troubles.

# Answer
> 7 votes
So they pushed a new version to GitHub late september:

https://github.com/WCHSoftGroup/ch34xser\_macos

This should be the maintained version ahead of what they offer as a download on the official website.

Common other issues:

* When reinstalling, make sure to first remove all old files:

```
sudo rm –rf /var/db/receipts/*CH34xVCPDriver*.*
sudo rm -rf /Library/Extensions/CH34xVCPDriver.kext

```

also don't forget to check for any related files in `/dev/` and the .app file in your applications folder if these already exist.

* Restart the device before reinstalling.
* Restart the device after installation.
* Try a different USB-Cable / USB-Hub.

Note: steps listed here were reportedly solutions I came across during my research which worked for other people and my colleagues. ~~For me it still doesn't work; but I am using a lot of unstable builds for my OS and other software that might interfere.~~

**Update February 2022:** Now with Monterey out of closed Beta this works like a charm for me. At least for the Web IDE.

# Answer
> 5 votes
After hours of mindless reinstalling of the drivers on M1, reboots and other magic tricks, I almost decided to switch to windows to make my arduino ide work. My NodeMCU board with CH340G would either show up as a serial port or not.

So I leave this message here as clearly many people struggling with M1 end up on this page: buy good microUSB cable. And I mean a good one. All problems disappeared right away. I had three cables at home but none was working - clearly most are only good for charging the phone, but suck at data transfer.

# Answer
> -1 votes
Worth the try. The .pkg file from here worked in my High Sierra. I've turned-on the "csrutil enable" before install, and it still worked...:

https://github.com/WCHSoftGroup/ch34xser\_macos

---
Tags: mac-os, ch340
---


# Question
Title: Wake-UP the ATtiniy44 from sleep_mode_pwr_down with a PushButton
I'm curently playing with sleep modes. When I push the button, melody starts, push again go to deep down sleep and save 3v battery, push again wake up and melody starts again. But seems like it doesn't completely goes to sleep and can't wake up.

```
#include <OneButton.h>
#include <avr/sleep.h>
#include <avr/power.h>

#define cs6 1109
#define fs5 740
#define d6 1175
#define c6 1047
#define f5 698
#define b5 988
#define e5 659
#define bf5 932
#define ef5 622
#define b4 494
#define g5 784
#define led1 8
#define led2 7

const uint16_t halloween[] PROGMEM = { cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5, cs6,  f5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
                                       fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4
                                     };

typedef enum {
  ACTION_OFF,
  ACTION_ON
}
MyActions;

const int buzzer = PA1;
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes = 218;
int noteDurations = 6;
int thisNote=0;
int ledState = LOW;

OneButton button(10, true, true);

MyActions nextAction = ACTION_OFF; // no action when starting

void setup() {
  pinMode(buzzer, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(10), wakeUpFromSleep, FALLING);
  button.attachClick(myClickFunction);

}

void melody () {

  unsigned long currentMillis = millis();

  if (thisNote <= 290 && currentMillis - previousMillis >= pauseBetweenNotes)
  {
    previousMillis = currentMillis;

    if (ledState == LOW) {

      ledState = HIGH;

      tone(buzzer, pgm_read_word(&halloween[thisNote]), 168);
      pauseBetweenNotes = 167 * 0.65;
      thisNote++;
    }

    else {

      ledState = LOW;
    }
    digitalWrite(led1, ledState);
    digitalWrite(led2, ledState);

  }
}

void wakeUpFromSleep() {
  // Rimuovi l'attivazione dell'interrupt per il pulsante
  detachInterrupt(digitalPinToInterrupt(10));
  sleep_disable();
  power_all_enable();
 }

void myClickFunction() {

  if (nextAction == ACTION_OFF)
  {
    nextAction = ACTION_ON;
    thisNote = 0;
    pauseBetweenNotes = 0;
    previousMillis = 0;
  }

  else
  {
    nextAction = ACTION_OFF;
    digitalWrite(led1, LOW);  // spegni i led
    digitalWrite(led2, LOW);
    noTone(buzzer);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_cpu();
  }
}

void loop() {

  button.tick();

  if (nextAction == ACTION_OFF) {
    wakeUpFromSleep();
  }

  else if (nextAction == ACTION_ON) {
    melody();
    }
}

```

# Answer
**EDIT** I've written the following programm. It should provide the requested features.

But for the time being I don't have access to an ATtiny44a so I used a Arduino UNO. I read both data sheets and did not find anything that prevents the program from running on a ATtiny44. So please try it and if it runs you can read the comments in the program to understand what I did to get it running.

I have a very "chirpy" button, so some times the program can not differ whether I clicked twice or the button bounces. I've used long debouncing periods to get rid of that. I've commented it in the code, please check what value works best for you.

Ah, And I've accellerated the the melody a little bit ;-). I like Heavy Metal more than Walzing Matilda style ;-). And I change the programm so that it runs the mellody again and again until you pressed the button again. Your Program stopped ofter playing the melody once.

```
// This Code is intended to run on an ordinary Arduino Uno
// The original request was to implement it for an ATtiny44a.
// I will document if there are difference to take
// into consideration. Most of the code should run on a
// attiny44 as well.

// The purpose of this program is to let the MCU play a melody
// started and stopped by clicking a button. The mcu should enter
// a enerngy saving sleep mode when the melody stops.
// When in sleep mode, pressing a button should wake up the MCU
// which then should continue playing the melody.

#include <avr/sleep.h>
#include <avr/power.h>

// The button pin must be pin two for Arduino Uno
// for a tiny any pin can be used so pin 2 is fine.
const int buttonPin = 2;
const int buzzerPin = 10;
const int led1 = 8;
const int led2 = 7;

// Attention!!!!: I use a pull up and a push button
// connected to GND.
// With this setup pressing the button will pull the pin to GND.
// Therefore we read LOW while the button is pressed.
// If the button is HIGH active - that means the button
// is connected to VCC - the LOW of the following constant must
// be changed to HIGH and the RISING must be changed to FALLEN.
#define BUTTON_PRESSED LOW
#define INTERRUPT_TRIGGER_METHOD RISING

// I decided to use a very long debounce delay, because I
// featured a very "chirpy" button. Feel free to experiment
// with this delay.
const long debounceDelay = 150L;

// setup for the melody

// define the note pitch values
#define cs6 1109
#define fs5 740
#define d6 1175
#define c6 1047
#define f5 698
#define b5 988
#define e5 659
#define bf5 932
#define ef5 622
#define b4 494
#define g5 784

// provide a melody as an array.
const uint16_t halloween[] PROGMEM = {
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  cs6, fs5, fs5, cs6, fs5, fs5, cs6, fs5,  d6, fs5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  c6,  f5,  f5,  c6,  f5,  f5,  c6,  f5,  cs6,  f5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  b5,  e5,  e5,  b5,  e5,  e5,  b5,  e5,  c6,  e5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  bf5, ef5, ef5, bf5, ef5, ef5, bf5, ef5,  b5, ef5,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4,
  fs5,  b4,  b4, fs5,  b4,  b4, fs5,  b4,  g5,  b4
};

//define processing variables for the play functionallity
unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes = 300;
unsigned long lengthOfActiveNote = 300;
int noteCounter = 0;
boolean toneOn = false;

// handling the play mode
// after inserting the battery the melody does not play.
// After the user will have pushed and released
// the push button, we will start with the melody.
volatile boolean playMelody = false;
volatile bool playModeChangeRequested = false;

// reading and debouncing the button
volatile unsigned long lastDebouncingMillis = 0;

void stopTheMelody()
{
  noTone(buzzerPin);
  toneOn = false;
  digitalWrite(led1, toneOn);
  digitalWrite(led2, toneOn);
}

void startTheMelody()
{
  previousMillis = 0;
  pauseBetweenNotes = 0;
  noteCounter = 0;
  toneOn = false;
  digitalWrite(led1, toneOn);
  digitalWrite(led2, toneOn);
}

void melody ()
{
  unsigned long currentMillis = millis();
  if (! toneOn &&
      (currentMillis - previousMillis) > pauseBetweenNotes)
  {
    pauseBetweenNotes = 167 * 0.2;
    tone(buzzerPin, pgm_read_word(&halloween[noteCounter]));
    noteCounter++;
    if (noteCounter > 290)
    {
      // the old program plays the melody only once
      // with resetting the note counter to 0
      // the melody start again and again.
      noteCounter = 0;
    }
    toneOn = true;
    digitalWrite(led1, toneOn);
    digitalWrite(led2, toneOn);
    previousMillis = currentMillis;
  }
  else if(toneOn &&
          (currentMillis - previousMillis) > lengthOfActiveNote)
  {
    lengthOfActiveNote = 58;
    noTone(buzzerPin);
    toneOn = false;
    digitalWrite(led1, toneOn);
    digitalWrite(led2, toneOn);
    previousMillis = currentMillis;
  }
}

// This is the interrupt service routine.
// It is called every time the button will have been released.
void ISR_buttonReleased()
{
  // Here, we know that this ISR is called because,
  // the button was released.
  lastDebouncingMillis = 0L;
  playModeChangeRequested = true;

  if (!playMelody)
  {
    // if the interrupt was triggered while the MCU was sleeping
    // we need to switch off the sleep mode to resume
    // normal activity. Otherwise the debouncing method does not
    // work, as it is done by code outside of the ISR.
    sleep_disable();
    power_all_enable();
  }
}

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(buzzerPin, OUTPUT);

  // paranoia setup
  playMelody = false;
  playModeChangeRequested = false;
  lastDebouncingMillis = 0;

  // the interrupt is triggered on rising edge, i.e.
  // when the button will be released
  attachInterrupt(
       digitalPinToInterrupt(buttonPin),
       ISR_buttonReleased,
       INTERRUPT_TRIGGER_METHOD);

  // stop melody and sleep
  stopTheMelody();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu();
}

void loop()
{
  // lastDebouncingMillis will be set to 0 1st) in the
  // setup routine and 2nd) in the ISR.
  if (lastDebouncingMillis==0 ||
      digitalRead(buttonPin)==BUTTON_PRESSED)
  {
    // Here lies the magic!
    // We synchronize the ISR, the sleep mode, a long button
    // press without release and the
    // button bouncing with this single if statement.
    lastDebouncingMillis = millis();
  }

  if (playModeChangeRequested)
  {
    unsigned long tempMillis = millis();
    if((tempMillis - lastDebouncingMillis) > debounceDelay)
    {
      playModeChangeRequested = false;
      playMelody = !playMelody;
      if (!playMelody)
      {
        // stop melody and sleep
        stopTheMelody();
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_enable();
        sleep_cpu();
      }
      else
      {
        startTheMelody();
      }
    }
  }

  if(playMelody)
  {
      melody();
  }
}

```

**Old Answer removed**

The old answer was not clear enough for this complicated topic.
> 2 votes

---
Tags: sleep
---


# Question
Title: The gateway is not working in Arduino EthernetENC
I am using ENC28J60 and EthernetENC library to connect an Arduino UNO with ATmega328 to the network. Everything works fine within the local network, but outside of it, I cannot ping the device. What could be the problem? The network settings are 100% correct (other devices work fine, and examples from the Ethernet library also respond to pings).

```
////////////////////////////////////// Settings //////////////////////////////////////
#define DHCP false          // true/false
#define CUSTOM_MAC true     // true/false

#if CUSTOM_MAC              // if true you can enter your custom mac address
#define MAC 0x00,0x5f,0x1C,0x05,0x5f,0x1C
#else
#define MAC 0x00,0x5f,0x1C  // Organizationally Unique Identifier (OUI)
#endif

#define IP_ADDRESS  192,168, 11,242
#define SUBNET      255,255,255,248
#define GATEWAY     192,168, 11,241
#define DNS         192,168, 11,241

// #define UIP_CONF_MAX_CONNECTIONS 0
///////////////////////////////////// Libraries //////////////////////////////////////
#include <Arduino.h>
#include <EthernetENC.h>  // Include the Ethernet library
#include <Agentuino.h>    // SNMP library
#include <EEPROM.h>
#include <microDS18B20.h>
/////////////////////////////// Arduino sensor pins //////////////////////////////////
#define TEMPERATURE_1_PIN 0
#define TEMPERATURE_2_PIN 1
#define TEMPERATURE_3_PIN 2
#define TEMPERATURE_4_PIN 3
#define SENSOR_220V_PIN   4
#define SERVO_PIN         5
#define LED_ALERT_PIN     6
#if !SOUND_MUTE
#define SPEAKER_PIN       7
#else
#define SPEAKER_PIN       8
#endif
#define FLOOD_PIN         A0
#define DOOR_PIN          A1
#define GAS_PIN           A2

///////////////////////////// Ethernet / SNMP init ///////////////////////////////////
#if !DHCP
IPAddress ip(IP_ADDRESS);   // IP Address for arduino
IPAddress gateway(GATEWAY); // Gateway for arduino
IPAddress subnet(SUBNET);   // SubNet mask for arduino
IPAddress myDns(DNS);       // DNS for arduino
#endif

byte mac[] = {MAC};

//////////////////////////////////// My OIDs /////////////////////////////////////////
...
//////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////// function SNMP resived ////////////////////////////////
void pduReceived(){...}
//////////////////////////////////////////////////////////////////////////////////////

void setup(){
  ///////////////////////////////// init pins ////////////////////////////////////
  pinMode(TEMPERATURE_1_PIN, INPUT);
  pinMode(TEMPERATURE_2_PIN, INPUT);
  pinMode(TEMPERATURE_3_PIN, INPUT);
  pinMode(TEMPERATURE_4_PIN, INPUT);
  pinMode(SENSOR_220V_PIN, INPUT);
  // pinMode(SERVO_PIN, INPUT);
  pinMode(FLOOD_PIN, INPUT);
  pinMode(DOOR_PIN, INPUT);
  pinMode(GAS_PIN, INPUT);
  pinMode(LED_ALERT_PIN, OUTPUT);
  #if !SOUND_MUTE
  pinMode(SPEAKER_PIN, OUTPUT);
  #endif

  ////////////////////////////// init other //////////////////////////////////////
  Serial.begin(9600); // Serial monitor init
  Agentuino.begin();  // Begin Snmp agent on Ethernet shield

  ///////////////////////// Generate random mac address //////////////////////////
#if !CUSTOM_MAC
  if (EEPROM[0] == 255 && EEPROM[1] == 255 && EEPROM[2] == 255){
    for (int i = 3; i < 6; i++){
      randomSeed(analogRead(A5));
      mac[i] = random(0xFF);
      EEPROM.put(i - 3, mac[i]);
    }
  }
  else{
    for (int i = 3; i < 6; i++){
      EEPROM.get(i - 3, mac[i]); // Reed saved mac addres from EEPROM
    }
  }
#endif

#if DHCP
  Ethernet.begin(mac) // Initialize Ethernet Shield in DHCP mode
#else
  Ethernet.begin(mac, ip, myDns ,gateway, subnet); // Initialize Ethernet Shield in static mode
#endif

///////////////////////////////////// Debug //////////////////////////////////////
Serial.println();
Serial.println();
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println(F("Ethernet shield was not found.  Sorry, can't run without hardware. :("));
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    delay(500);
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
  }

  Serial.print(F("localIP: "));
  Serial.println(Ethernet.localIP());
  Serial.print(F("dnsServerIP: "));
  Serial.println(Ethernet.dnsServerIP());
  Serial.print(F("gatewayIP: "));
  Serial.println(Ethernet.gatewayIP());
  Serial.print(F("subnetMask: "));
  Serial.println(Ethernet.subnetMask());
  Serial.print(F("mac: "));
  for (int i = 0; i < 6; i++){
    Serial.print(mac[i], HEX);
    if (i <= 4) Serial.print(F("."));
  }

  Serial.println();
  ////////////////////////////////////////////////////////////////////////////////

  Agentuino.onPduReceive(pduReceived);
  delay(10);
}

void loop(){
  Agentuino.listen();

  //////////////////////////////// Other code ////////////////////////////////////
  ...
  ////////////////////////////////////////////////////////////////////////////////
}

```

# Answer
From outside your local network (i.e the internet) you can only ping the external IP address of your router, local IPs such as your 192.168.11.242 are not routable on the internet. Additionally many home routers are configured to not respond to external pings. I see you're using snmp to communicate with your Arduino, you could forward the snmp port (normally port 161) from your router to the Arduino on 192.168.11.42:161 to achieve what you want but this is a security risk. You would then connect your snmp manager to your external IP address and your router would connect to your Arduino and do the required Network Address Translation to communicate. This assumes your router and internet provider allow port forwarding of the snmp port.
> 1 votes

---
Tags: arduino-uno, atmega328, ethernet, networking, enc28j60
---


# Question
Title: how to convert a line of code for arduino to receive a value
im sending the value 1500 from another MCU with

```
 fdserial_txChar(transmit, send >> 7);    // send Higher 7 bits
 fdserial_txChar(transmit, send & 0x7F);  // send Lower 7 bits

```

and was receiving it with code that looked like this

```
servo1  = fdserial_rxChar(receive) << 7;    // get Higher 7 bits
servo1 += fdserial_rxChar(receive) & 0x7F;  // get and add Lower 7 bits

```

how do i rewrite the receiving code so arduino will compile it?

Thank you.

here is the code im trying to get working

```
void setup() {
// physical pin 2=TX 3=RX
  Serial.begin(9600);
  pinMode(3, OUTPUT);      // set LED pin as output
  digitalWrite(3, LOW);    // switch off LED pin
}

void loop() {

  if (Serial.available()) {
  //  char data_rcvd = Serial.read();   // read one byte from serial buffer and save to data_rcvd

    int data_rcvd = Serial.read() << 7;     //get Higher 7 bits
    int data_rcvd += Serial.read() & 0x7F;  //get and add Lower 7 bits

    if (data_rcvd == 1500) digitalWrite(3, HIGH); // switch LED On
    if (data_rcvd == '0') digitalWrite(3, LOW);  // switch LED Off
  }

//  if (digitalRead(8) == HIGH) Serial.write('0');    // send the char '0' to serial if button is not pressed.
//  else Serial.write('1');                           // send the char '1' to serial if button is pressed.

}

```

# Answer
> 1 votes
You have a few obvious problems here.

---

> ```
> if (Serial.available()) {
>  int data_rcvd = Serial.read() << 7;     //get Higher 7 bits
>  int data_rcvd += Serial.read() & 0x7F;  //get and add Lower 7 bits
>
> ```

You are testing that one byte is available on the serial port and then reading two bytes. Too soon. Test for two bytes if you are planning to read two.

---

> ```
> if (data_rcvd == '0') digitalWrite(3, LOW);  // switch LED Off
>
> ```

Why the quotes? Why not: `if (data_rcvd == 0)` ?

---

How are you intending to synchronize the sending and receiving?

Your sender is sending `HLHLHLHL` \- what if the receiver starts while the low byte is being sent? You will receive `LHLHLH` which means your received data will be meaningless.

You are better off sending "readable" data, like "1500" rather than 1500, terminating with a newline, and structuring your receiving code to read until it hits a newline. That will synchronize the receiver (after the first reading, anyway).

---

For more tips about reading serial data see: How does serial communications work on the Arduino?

Also my post about serial data on my forum has code for buffering incoming serial data and waiting for a newline.

# Answer
> 1 votes
the answer to my question of how to write

```
servo1  = fdserial_rxChar(receive) << 7;    // get Higher 7 bits
servo1 += fdserial_rxChar(receive) & 0x7F;  // get and add Lower 7 bits

```

so Arduino would compile it is....

```
combined = (val1 << 7) | (val2);

```

---
Tags: code-review
---


# Question
Title: Arduino hangs / freezes - can't figure out why
I am building a remote controlled boat. My remote project freezes after an arbitrary amount of time. The serial stops output, the OLED doesn't update anymore and instructions are not send / received anymore.

For the life of me I cannot figure out why my project freezes. Using an Arduino Nano.

I have tried the following:

* Keep memory small
* Disable Serial as not to overflood
* Not use any risky variables; like String
* Determine if a specific circumstance causes the hang (X amount of time, certain instructions, losing radio connection, etc)
* Replace the Arduino
* Replace the power supply
* Replace the power supply cable
* Put the radio into debug mode, it becomes slow and nothing interesting shows on serial

Please provide help to allow me to continue my two-year long project. My gratitude for any pointers or help is unending.

The Arduino is connected to a NRF24L01 with adapter board, an OLED and two potentiometers.

This is my code:

```
#include <SPI.h>
#include "printf.h"
#include "RF24.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
#include <DifferentialSteering.h>

// Debugging mode:
int debugging_serial = 0;
int debugging_delay = 0;
int debugging_verbose = 0;

// Timers init;
unsigned long start_timer = 0;
unsigned long end_timer = 0;

// Oled state for clearing
int oledstate = 0;

// Create nRF24L01 transceiver using pins 9 and 10.
RF24 radio(9, 10);

// OLED init
#define I2C_ADDRESS 0x3C // 0X3C+SA0 - 0x3C or 0x3D
#define RST_PIN -1 // Define proper RST_PIN if required.
SSD1306AsciiAvrI2c oled;

// Set potentio meter pins
int pot_one_pin = A0;
int pot_two_pin = A1;

// Set Diff Steering
DifferentialSteering DiffSteer;

// Register two radio addresses to use for communication.
uint8_t address[][6] = { "1Node", "2Node" };

// Define sending and receiving payload structs. Note: these should be inversed on remote vs boat code
// DEFINE WHAT WE WILL BE SENDING
struct SendingPayloadObject
{
  // We are sending two numbers
  uint8_t Motor1Speed;
  uint8_t Motor2Speed;
};
// Also create the payload object to prepare and load with defaults in setup
SendingPayloadObject payload;

// DEFINE WHAT WE WILL BE RECEIVING
struct ReceivingPayloadObject
{
  // We are sending a message and a number
  char message[7];  // only using 6 characters for TX & ACK payloads
  uint8_t counter; // struct counter variable as example
};

void setup()
{
  if(debugging_serial)
  {
    Serial.begin(115200);
    Serial.println("Remote Code Started!");
  }

  // Oled setup
  // Call oled.setI2cClock(frequency) to change from the default frequency.
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
  //oled.setFont(System5x7);
  oled.clear();
  oled.println("Boat Remote Started!");
  oled.clear();

  // Check if radio works
  if (!radio.begin())
  {
    if(debugging_serial)
    {
      Serial.println(F("Radio hardware is not responding!"));
    }

    while (1) {}  // hold
  }

  // Set the PA Level low to try preventing power supply related problems
  // because these examples are likely run with nodes in close proximity to
  // each other. (RF24_PA_MAX is default)
  radio.setPALevel(RF24_PA_LOW);

  // To use ACK payloads, we need to enable dynamic payload lengths (for all nodes). ACK payloads are dynamically sized
  radio.enableDynamicPayloads();

  // Acknowledgement packets have no payloads by default. We need to enable this feature for all nodes (TX & RX) to use ACK payloads.
  radio.enableAckPayload();

  // Set the TX address of the RX node into the TX pipe and the opposite to the RX pipe. The remote radio address is 1!
  radio.openWritingPipe(address[1]);
  radio.openReadingPipe(1, address[0]);

  // Sender role code
  // Set payload defaults and put radio in send (TX) mode
  payload.Motor1Speed = 0;  // set the payload payloadMotor1Speed
  payload.Motor2Speed = 0;  // set the payload payloadMotor1Speed
  radio.stopListening();                 // put radio in TX mode

  if(debugging_verbose)
  {
    printf_begin();             // needed only once for printing details
    radio.printDetails();       // (smaller) function that prints raw register values
    radio.printPrettyDetails(); // (larger) function that prints human readable data
  }

  // DiffSteer init
  DiffSteer.begin(0);
}

void loop()
{
  //// REMOTE CONTROL STUFF:

  // NEW LOGIC FOR MANEURVERING
  int motorSpeed1 = 0;
  int motorSpeed2 = 0;

  // Steering using potentiometers
  int steering_pot_value = map(analogRead(pot_two_pin), 0, 1023, -127, 127);
  int power_pot_value = map(analogRead(pot_one_pin), 0, 1023, 0, 127);

  // Go Straight when steering almost straight
  if(steering_pot_value <= 15 && steering_pot_value >= -15)
  {
    steering_pot_value = 0;
  }

  // Compute differential steering
  DiffSteer.computeMotors(steering_pot_value, power_pot_value);

  // map motor outputs to needed range
  motorSpeed1 = map(DiffSteer.computedLeftMotor(), 0, 127, 0, 255);
  motorSpeed2 = map(DiffSteer.computedRightMotor(), 0, 127, 0, 255);

  // Corrective measures for smoother steering
  // Fix division by 0, full power when pot completley off
  if(power_pot_value <= 1) { motorSpeed1 = 0; motorSpeed2 = 0; };

  // OLED motor control code (for testing)
  //  Speeds directley from pot meters
  //  motorSpeed1 = map(analogRead(pot_one_pin), 0, 1023, 0, 255);
  //  motorSpeed2 = map(analogRead(pot_two_pin), 0, 1023, 0, 255);
  //

  // Set motor speeds in payload
  payload.Motor1Speed = motorSpeed1;
  payload.Motor2Speed = motorSpeed2;

  //// RADIO STUFF:

  // Let's time the tranmission for maagd / nerd purposes
  if(debugging_serial)
  {
     start_timer = micros();                  // start the timer
  }

  // Send over radio TX;
  bool report = radio.write(&payload, sizeof(payload));  // transmit & save the report

  if(debugging_serial)
  {
    end_timer = micros();                    // end the timer
  }

  if (report)
  {
    if(debugging_serial)
    {
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // print the timer result
      Serial.print(F(" us. Sent (Motor 1 Speed: "));
      Serial.print(payload.Motor1Speed);
      Serial.print(F(" , Motor 2 Speed: "));
      Serial.print(payload.Motor2Speed);
      Serial.print(F(")"));
    }

    // Define the pipe
    uint8_t pipe;

    if (radio.available(&pipe))
    {
      if (oledstate != 1) { oled.clear(); }; oledstate = 1;
      oled.set1X();
      oled.setFont(System5x7);
      oled.setCursor(0 , 0);
      oled.print("Transmission OK \n");
      oled.setCursor(0 , 30);
      oled.print("Motors L:");
      // Add leading zeroes to get true values (otherwise old number remains)
      if(payload.Motor1Speed < 100 && payload.Motor1Speed >= 10) { oled.print("0"); };
      if(payload.Motor1Speed < 10) { oled.print("00"); };
      oled.print(payload.Motor1Speed);
      oled.setCursor(80 , 30);
      oled.print("R:");
      if(payload.Motor2Speed < 100 && payload.Motor2Speed >= 10) { oled.print("0"); };
      if(payload.Motor2Speed < 10) { oled.print("00"); };
      oled.print(payload.Motor2Speed);

      // is there an ACK payload? grab the pipe number that received it
      ReceivingPayloadObject received;
      radio.read(&received, sizeof(received));  // get incoming ACK payload

      if(debugging_serial)
      {
        Serial.print(F(" Recieved "));
        Serial.print(radio.getDynamicPayloadSize());  // print incoming payload size
        Serial.print(F(" bytes on pipe "));
        Serial.print(pipe);  // print pipe number that received the ACK
        Serial.print(F(": "));
        Serial.print(received.message);    // print incoming message
        Serial.println(received.counter);  // print incoming counter
      }
    }
    else
    {
      if (oledstate != 2) { oled.clear(); }; oledstate = 2;
      oled.set1X();
      oled.setCursor(0, 0);
      oled.setFont(System5x7);
      oled.print("Transmission: \n \n");
      oled.setCursor(0, 80);
      oled.set2X();
      oled.print("No Reply (empty ACK)");

      if(debugging_serial)
      {
        Serial.println(F(" Recieved: an empty ACK packet"));
      }
    }
  }
  else
  {
    if (oledstate != 3) { oled.clear(); }; oledstate = 3;
    oled.set1X();
    oled.setCursor(0, 0);
    oled.setFont(System5x7);
    oled.print("Transmission: \n \n");
    oled.setCursor(0, 80);
    oled.set2X();
    oled.print("Failed");

    if(debugging_serial)
    {
      Serial.println(F("Transmission failed or timed out"));
    }
  }

  // Add a delay while programming for reading purposes
  if(debugging_verbose)
  {
    delay(10000);
  }
  else
  {
    if(debugging_delay)
    {
      delay(1000);
    }
  }
}

```

# Answer
A basic rule of debugging complex problems is to simplify the configuration until you get to a working baseline, and then build back up from there, one chunk at a time.

I would start with the simplest possible setup with a single RF transceiver at each end. No other peripherals, no other code; something that simply sends "hello" back and forth at wide spaced intervals - like once per second, to make sure there's no way the RF channel will be overloaded.

Once you get to a baseline where your test configuration will run indefinitely, then start adding code and/or peripherals, one at time, with a long-duration test at each step. Eventually you will reach a point where the system becomes intermittent; when this happens, back up one step to confirm proper operation, and then repeat this forward/back step until you are convinced that this is the step that produces the errant behavior.

Then divide the last step (the one that produces the bad behavior) into smaller steps, and find out which one of those steps produces the bad behavior, and eventually you will get down to one line of code, or one particular peripheral that causes the problem, and in all likelihood it will be something where you will say "OH! I should have thought of that long ago!".

Just as a last thought - you mentioned the 'if radio.availible()' function as a possible culprit. You could start the process by, for instance, modifying the library code (you can do this - it's just another bit of Arduino code) so that it simply returns 'true' (or false - doesn't matter) every time it is called. If your system operates OK with this setup, but doesn't operate OK with the original library code, then that may well be the source of the problem.

Looking at the RF24.cpp, I see that available() calls get\_status(), so maybe it is get\_status() that is hanging up.

Just some thoughts,

Frank
> 1 votes

---
Tags: programming, arduino-nano, nrf24l01+
---


# Question
Title: Why is Arduino not visible in MacOS USB port list?
When I connected my Arduino Nano 33 IoT to my 2017 iMac (Ventura OS), the USB port did not show in the Arduino IDE port list, even after double-clicking the Nano reset button to put it in the right mode. Installing the special CH34X device driver on the Mac for the USB port did not work either.

# Answer
> 1 votes
This is a common problem as judged by online questions. The most common solution seems to be to install the special CH34X device driver on the Mac for the USB port, but I'm suspecting many people actually have the same problem I did.

Have you heard of a “charge only” USB cable? I was skeptical, but I discovered that **four of my six USB-to-microUSB cables were charge-only!** If you want to communicate data￼, for example connecting your computer to an Arduino microprocessor to program it, the charge-only cable will not work.

How to tell the difference? There are four wires in the data-capable cable. The outside two on the connector are for charging and the inside two are￼ for data. If yours is missing the inside connectors, then it’s charge-only. But if it has them, it still might be charge-only. Use a meter to do a continuity check to test if those middle connectors are connected. You’ll need to use a little fine wire to get inside the little micro-USB connector to make contact, and you’ll probably need somebody to help you by holding one end in contact.

**As soon as I switched to a data-capable cable, the Nano USB port showed up in the IDE list!** (After double-clicking the Nano reset button).

After I got it working, I uninstalled the special driver I had installed, and it continued to work.

Thanks ptillisch on Arduino Team!

---
Tags: arduino-ide, arduino-nano, usb
---


# Question
Title: How to burn fuses in Digistump ATTiny85 with the Arduino IDE
I have a Digispark / digistump Attiny85. Working with Windows 11 and the Arduino IDE 2.0.4 I would like this guy to have Brown Out Detection set to 101 (2.7V)

For this, I'd need to set the BOD fuses.

How can I do this with the USB interface of the Arduino IDE? To use the USB programming, I have to set the Board to "Digispark (Default 16.5Mhz)".

I have seen that in normal ATTiny85 operation, under the Tools-Menu I could choose the fuses I like. In the Digispark Default setting this is not available.

# Answer
The first thing to say (already mentionened by @timemage) is that there is a large variety of "Digispark / Digistump" devices, both original, clones using the Micronucleus bootloader, even when considering only the ATTiny85 variants. Those variants, where the reset pin has not been re-configured as a GPIO pin, are easier to use. Otherwise, you firstly need a high voltage programmer to reset the ATTiny85 to its factory state, to restore the reset pin for configuring fuses etc.

The second thing is that the last post here: digistump.com/board/index.php/topic,2257.msg10556.html#msg10556 implies that 2.7v brown out, which you appear to need, is anyway already enabled (at least with the variant described by the author) That is, the fuse settings are: lfuse 0xE1 hfuse 0x5D efuse 0xFE.

Anyway, to change the fuses (or load the "Digispark / Digistump" (Micronucleus) bootloader) you need an ISP programmer (an Arduino or even another digispark can be configured as such). See: digistump.com/wiki/digispark/tutorials/programming. With the ISP programmer connected, you can then use AVRDUDE also to set the fuses.

In the worst case, you have to start with a factory condition ATtiny85 and go through the entire process of loading the "Digispark / Digistump" firmware onto it and configuring the appropriate fuse settings. See https://circuitdigest.com/microcontroller-projects/attiny85-ic-programming-through-usb-using-digispark-bootloader
> 3 votes

---
Tags: attiny85, fuses, arduino-ide-2
---


title: Sudden Error: File does not exist

text:
# Question
Title: Sudden Error: File does not exist
I am suddenly getting an error every time I try to compile code in the IDE, even though every one of the sketches previously compiled just fine:

```
Arduino: 1.8.13 (Windows 7), Board: "MH-ET LIVE Tiny88(16.0MHz)"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\lrhorer\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\lrhorer\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\lrhorer\Documents\Arduino\libraries -fqbn=mhetlive:avr:MHETtiny88 -ide-version=10813 -build-path C:\Users\lrhorer\AppData\Local\Temp\arduino_build_609285 -warnings=all -build-cache C:\Users\lrhorer\AppData\Local\Temp\arduino_cache_521731 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.micronucleus.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.micronucleus-2.0a4.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.avr-gcc.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -prefs=runtime.tools.avr-gcc-4.8.1-arduino5.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -verbose C:\Users\lrhorer\Documents\Arduino\sketch_feb27a\sketch_feb27a.ino

C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\lrhorer\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\lrhorer\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\lrhorer\Documents\Arduino\libraries -fqbn=mhetlive:avr:MHETtiny88 -ide-version=10813 -build-path C:\Users\lrhorer\AppData\Local\Temp\arduino_build_609285 -warnings=all -build-cache C:\Users\lrhorer\AppData\Local\Temp\arduino_cache_521731 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.micronucleus.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.micronucleus-2.0a4.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\tools\micronucleus\2.0a4 -prefs=runtime.tools.avr-gcc.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -prefs=runtime.tools.avr-gcc-4.8.1-arduino5.path=C:\Users\lrhorer\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.8.1-arduino5 -verbose C:\Users\lrhorer\Documents\Arduino\sketch_feb27a\sketch_feb27a.ino

Using board 'MHETtiny88' from platform in folder: C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\hardware\avr\1.0.0

Using core 'tiny88' from platform in folder: C:\Users\lrhorer\AppData\Local\Arduino15\packages\mhetlive\hardware\avr\1.0.0

Detecting libraries used...

"C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\4.8.1-arduino5/bin/avr-g++" -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -w -x c++ -E -CC -mmcu=attiny88 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_DIGISPARKPRO -DARDUINO_ARCH_AVR "-IC:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\mhetlive\\hardware\\avr\\1.0.0\\cores\\tiny88" "-IC:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\mhetlive\\hardware\\avr\\1.0.0\\variants\\tiny88" "C:\\Users\\lrhorer\\AppData\\Local\\Temp\\arduino_build_609285\\sketch\\sketch_feb27a.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE

exec: "C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\4.8.1-arduino5/bin/avr-g++": file does not exist

Error compiling for board MH-ET LIVE Tiny88(16.0MHz).

```

The file indeed does not exist in that location. What now?

Update: Under the ATTinyCore compiler the missing file name is the same, but the directory is different:

```
exec: "C:\\Users\\lrhorer\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++": file does not exist

```

The latest version of the DigiStump compiler does not even have the MH-ET Live Tiny88 board compiler included.

I can get the code to compile under Linux, but I am having trouble uploading the binary to the board. How can I take the binary code and upload it to the ATTiny88 board under either Linux or Windows 7?

Update: I found three files quarantined by my anti-virus. I restored the files, and now avr-g++.exe seems to be back where it belongs, and the compiler no longer claims the file is missing. Now, however, it s complaining about not finding the stdlib.h library called from the Arduino.h library.

Update: After I removed three files apparently related to the IDE from quarantine by my virus scanner, I deleted everything, and re-installed the IDE. Now it compiles without error, but I cannot upload to the board in either Windows or Linux. Of course I tried more than once to reinstall the Windows USB drivers, and they install without error, but the virtual device does not show up like it is supposed to, and the upload processor times out.

# Answer
> 0 votes
Deleting / uninstalling the entire IDE and completely reinstalling allowed the code to compile, so I am closing this question. It will not upload, so I will open another question.

---
Tags: arduino-ide, attiny
---


# Question
Title: LVGL v8.2 on ESP32-S3 colour issue ILI9341 TFT LCD Arduino IDE
I have ILI9341 320x240px TFT LCD screen which I am using with ESP32-S3-wroom-1 module.

I have tested with TFT\_eSPI and works fine, but when using LVGL, I am seeing weird artefacts on the edges.

I am using Arduino IDE

Started off the sketch from

https://github.com/lvgl/lvgl/blob/master/examples/arduino/LVGL\_Arduino/LVGL\_Arduino.ino

Havent changed sketch file much.

I am using LVGL latest v8.2.0

```
/*====================
   COLOR SETTINGS
 *====================*/

/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 16

/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP 1

/*Enable features to draw on transparent background.
 *It's required if opa, and transform_* style properties are used.
 *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/
#define LV_COLOR_SCREEN_TRANSP 1

/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
 * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
#define LV_COLOR_MIX_ROUND_OFS 0

/*Images pixels with this color will not be drawn if they are chroma keyed)*/
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00)         /*pure green*/

```

`LV_COLOR_SCREEN_TRANSP 1` was originally 0 changing it did not change anything.

I am following the FAQ which mentions

> 1.6.7 Why I see nonsense colors on the screen? Probably LVGL's color format is not compatible with your displays color format. Check LV\_COLOR\_DEPTH in lv\_conf.h. If you are using 16 bit colors with SPI (or other byte-oriented interface) probably you need to set LV\_COLOR\_16\_SWAP 1 in lv\_conf.h. It swaps the upper and lower bytes of the pixels.

as you can see above in the config, the values are as recommended.

Any help will be greatly appreciated.

# Answer
Turns out, I had to disable `LV_COLOR_16_SWAP` I had been trying with different colour depths and everything else, I still cannot see gradients drawn properly, but the colours seem to be correct now.
> 0 votes

---
Tags: esp32
---


title: GPS Ublox neo-6mv2

text:
# Question
Title: GPS Ublox neo-6mv2
I'm trying to get gps data from ublox neo-6mv2 module via arduino. Should ublox's neo-6mv2 light blink after power up by 5v from arduino ? Or is there any other sign that tells the module isnt dead ?

Module is connected to 5v, gnd for few hours - still no blink / light.

# Answer
> 0 votes
Be sure the active antenna is attached and may have to move it around to differnent areas of you work bench. some of these modules are very deaf or prone to inteference from reflections in the room.

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


# Question
Title: UltraSonic Sensor with an ESP-01 Standalone
I'm trying to build a cheap device to measure water level in a tank using HC-SR04 sensor and ESP-01 which send the data to MQTT topic. I used the same code with ESP-E12 which works just fine. As I'm trying to drive the cost down with ESP-01, I faced a problem with I/O pins. I searched the web and found some contradicting info about which pins could be used in this case.

So here is the schematic of my setup:

Coming to the ESP-01, I used a USB adapter to program it and the code uploaded successfully. Here I'm just showing the Ultrasonic sensor part which I believe I have issues with.

```
#define echoPin 2 // Echo Pin
#define trigPin 0 // Trigger Pin

long duration, distance; // Duration used to calculate distance

void setup(){
  Serial.begin (115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop(){
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2;
  Serial.println(distance);
  delay(200);
}

```

I read somewhere in the internet that GPIO2 can't be used and must be replaced with Rx = GPIO3. However, I tried that and it didn't work too.

**So the question here, am I really using the right pins or is it really possible to do that with esp-01?**

# Answer
This question is old, but myself had the same problem, so I will answer it.

The problem here seems to be that you have the GPIO0 and GPIO2 connected to the SR04 module when it is powered (this is how should be expected), but the GPIO0 and GPIO2 (also GPIO15, just for mention it), are used by ESP8266 to change the boot mode, with nothing connected to these pins, the ESP will load the program written in the flash, but if these pins change the levels while the ESP is powering up, it could enter in the Flash mode and your code will not execute. If you turn on the ESP-01 first and connect the wires to the SR04 just after, the code works, I know because I had the same problem and have the circuit in my front right now. But this is just for testing, you should not have to do that, the solution for me was to use the GPIO3.

You can use the pin RX as GPIO3 as you mentioned, but you can't use it at the same time that you are using the Serial, because Serial will use the RX and TX pins. If you write a Webserver to display the distance measured, for example, and remove the lines that use the serial, it will work. I used the GPIO3 and GPIO2 with the same code, just disabling serial and changing the pin numbers and worked.
> 1 votes

# Answer
There are 2 things here. Ultrasonic sensor works on 5V while ESP on 3.3V. So your sensor is sending 5V signal to ESP. It might fry your board but I believe it has a safety cut off of everything above 3.3V and that's the reason your application is not working. Cheap solution would be adding voltage divider to your Echo pin: https://randomnerdtutorials.com/how-to-level-shift-5v-to-3-3v/ but then you will face the issue mentioned by Juraj above. You may then overpass that issue manually or look for more sophisticated (expensive) solution.
> -1 votes

---
Tags: esp8266, ultrasonics
---


title: How to store a struct in a file?

text:
# Question
Title: How to store a struct in a file?
I'm trying to store (read&write( a struct using `LittleFS` on ESP8266.

Appreciate assistance

```
struct oper_string
{
  bool state;     /* On or Off */
  uint8_t step;   /* Step, in case of PWM */
  uint8_t reason; /* What triggered the button */
  time_t ontime;  /* Start Clk */
  time_t offtime; /* Off Clk */
};

```

# Answer
you can think of a struct as an array (group) of variables which might be of a different sizes and struct helps you take specific portion of this string. Lets say you have a struct of

```
struct foo{
   bool first;
   uint8_t Second;
   uint16_t Third;
} structMember;

```

Then it is stored in a row in exactly same order as they have been defined

```
---------------------------
| bool | uint8_t | uint16_t|
|1 byte| 1 bytes | 2 bytes |
--------------------------
1B+1B+2B = sizeof(srtuctMember)

```

File.write() saves date in a file in block of 1Byte each.

When you send array to the function it actualy receives only a ***pointer*** to its beginning. That is why many functions take a size as a second argument.

When you send a data into a function in a format its not designed to take you can tell the compiler that the function should trait it as a different type of variable. Lets say we have function defined as `void sampleFunction(byte var1)` then we can use it by

```
char x='j';
sampleFunction((byte) x);

```

which tells compiler to treat 'x' as if it was `byte`.

when you pass array you are not really passing the actual data, but an information where the data is(same with the struct member), so by putting asterisk after the definition you are telling compiler the format of data it ***points*** to. and when you read it back you will get all the contend back as same data in same order... which struct then divides in a same way

```
file.write((byte*) &StructMember,sizeof(structMember));

```
> 4 votes

# Answer
Just as a complement to Tomas' answer (which is perfectly valid), I would like to point out that consecutive members of a struct may not be adjacent in memory. Some structs have padding within them, which is needed to satisfy alignment requirements.

The struct given by Tomas as an example will not have padding, but yours may. For example, on my 64-bit PC, your struct is stored as follows:

| offset | size | member |
| --- | --- | --- |
| 0 | 1 | state |
| 1 | 1 | step |
| 2 | 1 | reason |
| 3 | 5 | (padding) |
| 8 | 8 | ontime |
| 16 | 8 | offtime |

In the table above, “offset” is the position of the member relative to the start of the struct. The padding after `reason` is needed in order to align `ontime` at an address that is multiple of 8. Your ESP being a 32-bit machine, it is likely to use only a single byte of padding.

Padding may be an issue for two reasons:

1. It can differ between computer architectures. Thus, if you plan to write the file on the ESP and read it back on your PC (or vice versa), it is one of the possible sources of incompatibility, the others being endianness and member sizes.
2. It is a waste of disk space, although this might not be an issue if you are only loosing 1 byte out of 20.

If padding can be problematic, the only valid option is to write and read the struct one member at a time. Conversely, if the file is only ever going to be accessed by the ESP, and you don't mind loosing a few percent of the file to padding, then don't worry, follow Tomas' advice, and read and write the struct as an array of bytes: it is just simpler.
> 3 votes

# Answer
one can write a struct directly into a SPIFS/ FFAT file like this:

```
 * EXAMPLE READING AND WRITING A C++ STRUCT TO A FILE
 */
#include <FS.h>
#include <SPIFFS.h>

typedef struct {
  char someString[10];
  float someFloat;
} MyStruct;

MyStruct myStruct = { "test test",1.7 };

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  if(!SPIFFS.begin()){
      Serial.println("Card Mount Failed");
      return;
  }

  strncpy( myStruct.someString, "testtesttest", sizeof(myStruct.someString) );
  File myFile = SPIFFS.open("/somefile.txt", FILE_WRITE);
  myFile.write((byte *)&myStruct, sizeof(myStruct));
  myFile.close();
}

void loop() {
  // put your main code here, to run repeatedly:
  File myFile = SPIFFS.open("/somefile.txt", FILE_WRITE);
  myFile.read((byte *)&myStruct, sizeof(myStruct));
  myFile.close();
  Serial.printf( "read: %s, %.2f\n", myStruct.someString, myStruct.someFloat );
  delay(1000);
}

```

the code above is available on this Github Gist.
> 0 votes

---
Tags: esp8266, spiffs, littlefs
---


# Question
Title: I am attempting to control two stepper motors by using serial input. My code works, however I have to press the new directional command multiple times
I am using two 28BYJ-48 stepper motors with two motor drivers that they come with. (I don't know the name of them.)

Here is my code:

```
/*
 * Code to control two stepper motors simultaneously using the stepper library function calls
 * This code has functions which make calls to initiate one step from each of the two motors at a time
 * therefore each motor takes it in turn to step with the end result of them both running together
 * the variable 'lastCall' allows for a continuous input to keep the steppers running if there is no serial input
 * Written by Gabriel Adams  - March 2023 -
 */
#include <Stepper.h>

//definitions for each command to be recieved via serial port
#define COMMAND_LEFT 'a'
#define COMMAND_RIGHT 'd'
#define COMMAND_FORWARD 'w'
#define COMMAND_BACK 's'
#define COMMAND_STOP ' '

//Number of steps per internal motor revolution
const float STEPS_PER_REV = 32;

//Amount of gear reduction
const float GEAR_RED = 64;

//Number of steps per geared output rotation
const float STEPS_PER_OUT_REV = STEPS_PER_REV * GEAR_RED;

//enter the steps per rev for your motors here
int stepsInRev = STEPS_PER_OUT_REV ;

//this sets the value for the for loops and therefore sets the amount of steps in each call
int num_of_steps = 1;
// setup pins for each driver motor1 ~ IN1, IN2, IN3, IN4; motor2 ~ IN1, IN2, IN3, IN4
Stepper myStepper1(STEPS_PER_OUT_REV, 4, 6, 5, 7);
Stepper myStepper2(STEPS_PER_OUT_REV, 8, 10, 9, 11);
// variable to store the last call to the serial port
char lastCall = ' ';

//I had prototyped all of the functions here, but for some reason the Arduino IDE didn't like it
//so they are coded out until I an figure out why
//void forwardStep();
//void backwardStep();
//void leftStep();
//void rightStep();
//void allStop();

//to move the motors forward
void forwardStep(int steps){
  Serial.println("forward");
  // step one step each forward
  myStepper1.step(1);
  myStepper2.step(1);
  delay(10);
}

// to move the motors back
void backwardStep(int steps){
  Serial.println("backward");
  // step one step each backward
  myStepper1.step(-1);
  myStepper2.step(-1);
  delay(10);
}

// to move the motors in opposite directions (left)
void leftStep(int steps){
  Serial.println("left");
 // step one step each left
  myStepper1.step(1);
  myStepper2.step(-1);
  delay(10);
}

// to move the motors in opposite directions (right)
void rightStep(int steps){
  Serial.println("right");
  // step one step each right
  myStepper1.step(-1);
  myStepper2.step(1);
  delay(10);
}

// to power down the motor drivers and stop the motors
void allStop(){
  Serial.println("stop");
  // steppers stop
  PORTD = B00000000; //sets all of the pins 0 to 7 as LOW to power off stepper1
  PORTB = B00000000; //sets all of the pins 8 to 13 as LOW to power off stepper2
}
void setup() {
  Serial.begin(9600);//start the bluetooth serial port - send and recieve at 9600 baud
  // set the speed at 60 rpm:
  myStepper1.setSpeed(700);
  myStepper2.setSpeed(700);
}

void loop() {
//check to see if there is serial communication and if so read the data
if(Serial.available()) {
char data = (char)Serial.read();
// switch to set the char via serial to a command
switch(data) {
  case COMMAND_FORWARD:
    forwardStep(num_of_steps);
    break;
  case COMMAND_BACK:
    backwardStep(num_of_steps);
    break;
  case COMMAND_LEFT:
    leftStep(num_of_steps);
    break;
  case COMMAND_RIGHT:
    rightStep(num_of_steps);
    break;
  case COMMAND_STOP:
    allStop();
    break;
}
// set the 'lastCall' variable to the last call from the serial
lastCall = data;
}

char data = lastCall;

Loop(lastCall);
Serial.read();

}

void Loop(char x){
switch(lastCall) {
  case COMMAND_FORWARD:
    forwardStep(num_of_steps);
    break;
  case COMMAND_BACK:
    backwardStep(num_of_steps);
    break;
  case COMMAND_LEFT:
    leftStep(num_of_steps);
    break;
  case COMMAND_RIGHT:
    rightStep(num_of_steps);
    break;
  case COMMAND_STOP:
    allStop();
    break;
}
return lastCall;

(char)Serial.read();
}

```

# Answer
The problem is, that you are reading from the Serial buffer without using the data. There are three places in your code, where you use `Serial.read();`:

1. You use in in the block with your serial code and you set `lastCall` accordingly. This is ok.
2. Then you use it at the end of `void loop()`, but you don't assign the value to anything.
3. And you use it at the end of your own `Loop()` function, again without assigning the value to anything.

Short explanation how `Serial` works: The Uno has hardware to handle Serial communication in the background via interrupts. The data arrives at the Uno and gets automatically (in the background) places in the internal buffer of the `Serial` object. The call to `Serial.read()` removes the oldest byte from the buffer (so that you get the bytes in order of arrival) and returns it. If there is no new data byte available it will return `-1`.

So when you just use `Serial.read()` without assigning the value to anything, you are basically throwing away data bytes from the Serial buffer.

> I was thinking the Serial.read() command would ensure more immediate reads of serial inputs.

Reading the data from the buffer is not enough. You actually have to do something with it. Otherwise you are just reading without reacting. So please remove the two calls to `Serial.read()`, only leaving the the one in your `if(Serial.available())` block.

> how at the moment it won't immediately change direction when I give a new command, how do I utilize the Serial.read() command to quickly move to a new loop?

You should remove all the calls to `delay()`. Currently your code spends the most time in these delays, doing nothing. Instead you can use the non-blocking coding style from the `BlinkWithoutDelay` example, that comes with the Arduino IDE. It uses `millis()` as a time keeper, only executing the code (blinking an LED in the example; doing a step in your code) when it is time to do so. There are many tutorials about that online.

If you want you can even go further and switch to the `AccelStepper` library, which is more capable than the standard `Stepper` library. It lets you set the speed and acceleration and then you simply run the motor by executing the `run()` method often enough. No need for your own timing of steps then, because the library is handling that. Though this will be a bigger change to your code.
> 0 votes

---
Tags: arduino-uno, stepper-motor
---


title: Checking size in flash memory Esp32

text:
# Question
Title: Checking size in flash memory Esp32
I recently purchased an Esp32 and am doing some tests using Arduino IDE. In one of the tests, I am recording a lot of .txt files with some text inside them in the flash memory, however, I would like to know how I can check the remaining space in the flash memory. I'm checking the flash memory space with `Serial.println(ESP.getFlashChipSize());`, however, the returned value is always the same.

Is this the right command to check? Why is it always with the same value?

# Answer
> Is this the right command to check? Why is it always with the same value?

The only way that size can change is if you desolder the can from the top of the ESP32 module, then desolder the flash chip, and replace it with one that has a different capacity.

The free space is not a function of the flash chip. It is a function of the filesystem you are using to store your data - be that SPIFFS or FAT.

You should check the manual for the filesystem you are using to find what functions there are pertaining to space usage.
> 1 votes

# Answer
The file system on the ESP32 is stored in a portion of the flash memory, and managed by the SPIFFS (SPI Flash File System) library. You can use the `SPIFFS.info()` function to get information about the file system, including the total size and the used size.

Assuming you have SPIFFS:

```
#include <ESP.h>
#include <SPIFFS.h>

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

  // Initialize the SPIFFS file system
  if (!SPIFFS.begin(true)) {
    Serial.println("Initialization failed!");
    return;
  }

  // size of the compiled program
  uint32_t program_size = ESP.getSketchSize();

  // size of the file system
  FSInfo fs_info;
  SPIFFS.info(fs_info);
  uint32_t file_system_size = fs_info.totalBytes;

  // used size of the file system
  uint32_t file_system_used = fs_info.usedBytes;

  // free size in the flash memory
  uint32_t free_size = ESP.getFlashChipSize() - program_size - file_system_size + file_system_used;

  Serial.print("Program size: ");
  Serial.print(program_size);
  Serial.println(" bytes");

  Serial.print("File system size: ");
  Serial.print(file_system_size);
  Serial.println(" bytes");

  Serial.print("File system used: ");
  Serial.print(file_system_used);
  Serial.println(" bytes");

  Serial.print("Free space: ");
  Serial.print(free_size);
  Serial.println(" bytes");
}

void loop() {
  // Do Nothing Here
}

```
> 2 votes

# Answer
Serial.println(ESP.getFlashChipSize()); don't return the physical flash size, it just returns the flash size that you have selected in the Arduino IDE Flash size. Just try to set Flash size "2MB (16Mb)" And the result is '2097152'
> 0 votes

---
Tags: arduino-ide, esp32
---