title: Making library for arduino

text:
# Question
Title: Making library for arduino
I'm learning library making on arduino , I want to make a library that works with arrays a user sets, e.g:

User sets array of int, when a certain function is been called the library will check if some instance are true or not ann set the return function accordingly as the array.

Code example:

```

    //in project example

#include <Keyss.h>

int rows=4;
int cols=2;
int a=0;
int b=1;
int c=2;
int inp=3;
int keyss[4][2]={
{0,1},,
{2,3},
{4,5},
{6,7}
};

Key key((keyss),rows,cols,inp,a,b,c);

void setup(){
Serial.begin(9600);
int keyprint=key.getkey();
Serial.println(key print);
}
void loop(){
}

```

And this will be the library files Keys.h

```

#ifndef KEYSS_H
#define KEYSS_H
#include <Arduino.h>

class Key {

public:

Key(int (*keys)[4],int rows,int cols,int inp,int t1,int t2,int t3);
int getkey();
int waitforkey();

private:

int *_keys;
int _rows;
int _cols;
int _inp;
int _t1;
int _t2;
int _t3;

};

#endif

```

And Keys.CPP

```

#include <Keyss.h>

//initialization

Key::Key(int (*keys)[4],int rows,int cols,int inp,int t1,int t2,int t3){

 _keys=keys[4];
 _rows=rows;
 _cols=cols;
 _inp=inp;
 _t1=t1;
 _t2=t2;
 _t3=t3;

 pinMode(_inp,INPUT);
 pinMode(_t1,OUTPUT);
 pinMode(_t2,OUTPUT);
 pinMode(_t3,OUTPUT);

}

//getkey()

int Key::getkey(){

int _a;
int _b;
int _i=0;
int _keymap=false;
int _val;
int _dt=500;
int _s1;
int _input;

for(_a=0;_a<_rows;_a++){

 for(_b=0;_b<_cols;_b++){

  _s1=_i;
  digitalWrite(_t1,(_s1>>0)&1);
  digitalWrite(_t2,(_s1>>1)&1);
  digitalWrite(_t3,(_s1>>2)&1);
  delayMicroseconds(_dt);

  _input=digitalRead(_inp);

  if(_input==true && _keymap==false){

   _val=_keys[_a*_cols+_b];
   _keymap=true;
}

  _i++;

}
}

if(_keymap==false){
   _val=-1;
}

return _val;

}

//waitforkey()

int Key::waitforkey(){

int _waitfor=getkey();

while(_waitfor<0){

_waitfor=getkey();

}

return _waitfor;

}

```

Where I have problem now is I don't know how to use or assign an array in a library I don't know how to use functions to refer to an array a user inputes, like here

```
int keyss[4][2]={
{0,1},
{2,3},
{4,5},
{6,7}
};

```

How do I use a function or inside the library to refer to the array a user sets?

Please how do I achieve that?

Its giving this error

# Answer
> 2 votes
Your `keys` variable is a 2D array of `int`, i.e. it is an array of arrays. In C++, when an array is assigned to a variable or passed as an argument, it implicitly decays to a pointer to its first element. Note, however, that the decay-to-pointer behavior is not recursive. In this case you end up with a pointer to an array of three `int`.

Your code should work if you give the proper type to the `_keys` class member and the `keys` constructor parameter:

```
class Key {
public:
    Key(int (*keys)[3], int trig1, int trig2, int trig3, int inpin);
    int getkey();

private:
    int (*_keys)[3];  // pointer to array of 3 int.
    int _trig1;
    int _trig2;
    int _trig3;
    int _inpin;
    int _keye;
};

```

---

**Edit**: You have completely changed the question, to the point that my answer may not be relevant anymore. In the previous version of the question, it looked like you wanted to use a 3×3 2D array of numbers in the class. In the current version, you are using an array of arbitrary sizes represented as a flattened 1D array. These are quite different approaches.

If you want to use a 2D array, the number of *columns* has to be a compile-time constant. You have to declare the member variable as a pointer-to-array like this:

```
int (*_keys)[2];  // there are two columns, not four!

```

assign it like this:

```
_keys = keys;  // do NOT subscript keys

```

and use it like this:

```
_val = _keys[_a][_b];  // it is a 2D array

```

This approach cannot work if you do not know the number of columns beforehand.

If you want to use a flattened (1D) array, then the parameter of the constructor has to be a simple `int*`, and you have to give it the address of the first element of the original 2D array:

```
Key key(&keyss[0][0], rows, cols, inp, a, b, c);

```

The drawback of using a flattened array is that, in order to access the elements, you have to perform explicit index calculations:

```
_val = _keys[_a*_cols + _b];

```

---
Tags: arduino-uno, library, keypad
---


# Question
Title: How to trigger a function by detecting voltage change?
```
#define monitor_pin 14

void setup()
{
  pinMode(monitor_pin , INPUT);
}

void loop()
{
    unsigned long d1 = pulseIn(14, HIGH);
    if (d1>0){//trigger function}
}

```

I know there is a function pulseIn(), but it doesnt really solve my problem. I just want to trigger a function when voltage change from LOW to HIGH/HIGH to LOW. pulseIn() need to wait for the voltage to back to original level which in my case will exceed 3 minutes and cause timeout.

How can I detect a voltage change other than pulseIn()?

# Answer
> 3 votes
You can save the previous state of the pin and then trigger the function when the current state is different from the previous state:

```
#define monitor_pin 14
int previous_state;

void setup()
{
  pinMode(monitor_pin , INPUT);
  previous_state = digitalRead(monitor_pin); // Initialize previous state with initial reading of the pin
}

void loop()
{
  int current_state = digitalRead(monitor_pin);
  if(current_state != previous_state){
    // Execute your code here
    previous_state = current_state; // update previous state
  }
}

```

---
Tags: voltage-level, voltage, pulsein
---


title: How to show the º character in a LCD?

text:
# Question
Title: How to show the º character in a LCD?
I have a 16x2 LCD and I want to show a temperature: **23 ºC**.

But the **º** symbol is not properly shown. It shows a strange character instead of the **º** symbol .

# Answer
It depends on the exact model of LCD you are using. Or more exactly, on the Dot Matrix Liquid Crystal Display Controller/Driver, like the Hitachi HD44780U that is used in many 16x2 LCD.

For that driver, you have a table of native chars, like this:

In this table, the char "°" is at col 0b1101, row 1111, (0xDF, or 223). But, you have to cast that value to a char before displaying, otherwise you will get the value (223), not the symbol.

```
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.print("temp 27");
  lcd.print((char) 223);
  lcd.print(" ");
  lcd.print(223);

}

void loop()
{
}

```
> 17 votes

# Answer
Some displays have different characters above 128. It is best to make your own character.

That is what @dannyf ment with "CGRAM". The custom characters are stored in CGRAM. There is no need to read the datasheet though, because there is a function in the Arduino LiquidCrystal library for it.

Start here: Arduino CreateChar reference
There are even websites that help you to create the character: omerk and maxpromer.
> 5 votes

# Answer
Easy.

1. Pull up the datasheet and pick the character that most resembles your symbol. Char 0b11011111 looks the best to me but 0b10110000 isn't bad.
2. While you are in the datasheet, check out CGRAM.
> 0 votes

# Answer
do `lcd.write(223);` Transform the Decimal into an ASCII symbol.
> 0 votes

---
Tags: lcd, display
---


# Question
Title: Trying to move a stepper motor back and forth
So, I am trying to move a stepper motor through a halfway revolution (1024 steps), and once that is completed, have it move back and forth by about 100 steps in either direction.

I am having some trouble with this though, because while it will move in one direction, it will not move in the other.

```
void setup()
{
    stepper1.setMaxSpeed(1000);
    stepper1.moveTo(1024);
    stepper1.setAcceleration(100);
    Serial.begin(19200);
    while(!Serial);
}

void loop()
{
    stepper1.run();
    static int ctr = 0; //counter value to store how many times the back and forth motion has occured
    if(stepper1.currentPosition() == 1024){
      backMotion(stepper1.currentPosition());
      forthMotion(stepper1.currentPosition());
      ctr++;
    }
//    if(stepper1.currentPosition() == 824 && ctr > 0 && ctr < 30){
//      forthMotion(stepper1.currentPosition());
//    }
}

void backMotion(int value){
    int current = value;
    int back_distance = current - 200; //distance to move back by
    stepper1.moveTo(back_distance);
}

void forthMotion(int value) {
  int current = value;
  int forth_distance = current+200;
  stepper1.moveTo(forth_distance);
}

```

So, when I call the forthMotion function right after the backMotion function, it will just move forward. Which makes no sense to me. Shouldn't it be moving backwards, and then forwards in an infinite loop? Because it will hit 1024, go back to 824, hit 1024 again, and so on and on...

Also, when I call the backMotion function, isn't the Arduino code supposed to be blocking in that, nothing else gets executed while that is running?

Edit: The code seems to work when I uncomment the if statement in the loop function.

# Answer
> 1 votes
I guess the solution might be this:

in back motion

```
void backMotion(){

    int back_distance = - 200; //distance to move back by
    stepper1.moveTo(back_distance);
}

```

In forward motion

```
void forthMotion() {

  int forth_distance = 200;
  stepper1.moveTo(forth_distance);
}

```

In loop

```
void loop()
{
    stepper1.run();
    static int ctr = 0; //counter value to store how many times the back and forth motion has occured

    stepper1.moveTo(1024);
    while(ctr < 30){

      backMotion();
      delay(500);

      forthMotion();
      delay(500);
      ctr++;
    }
//    if(stepper1.currentPosition() == 824 && ctr > 0 && ctr < 30){
//      forthMotion(stepper1.currentPosition());
//    }
}

```

Your main code will be like this

```
void setup()
{
    stepper1.setMaxSpeed(1000);
    stepper1.moveTo(1024);
    delay(3000); // wait till stepper gets to destination
    stepper1.setAcceleration(100);
    Serial.begin(19200);
    while(!Serial);
}

void loop()
{
    stepper1.run();
    static int ctr = 0; //counter value to store how many times the back and forth motion has occured

    while(ctr < 30){

      backMotion();
      delay(500);

      forthMotion();
      delay(500);
      ctr++;
    }
//    if(stepper1.currentPosition() == 824 && ctr > 0 && ctr < 30){
//      forthMotion(stepper1.currentPosition());
//    }
}

void backMotion(){

    int back_distance = - 200; //distance to move back by
    stepper1.moveTo(back_distance);
}

void forthMotion() {

  int forth_distance = 200;
  stepper1.moveTo(forth_distance);
}

```

# Answer
> 0 votes
Steppers don't typically have feedback about their position (as opposed to servos). Normally you're just telling a stepper how much and how quickly to rotate. As opposed to servos, which you tell which position to rotate to.

Are you sure you're using a stepper?

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


# Question
Title: Help using uint32_t? Trying to feed arduino serial from raspberry pi. Any help is very very much appreciated
So I don't know C so I'm just trying to get some very very basic code running on my arduino to send it commands over serial.

I'm feeding serial into buf

irsend.sendNEC(0x210704FB, 32)

this works but I need to read from buf instead of hardcoding for one code.

irsend.sendNEC(buf, 32) won't compile but irsend.sendNEC((uint32\_t) buf, 32) will. It just doesn't do anything.

When I use

serial.print((uint32\_t) buf, 32);

it prints just seemingly random letters?

I'm trying to just feed it a serial code with a language I know a little better. I can send the hex code over serial with python but I don't know the first thing about C. I don't understand why I can't just feed it a variable and have it read it as is. here's my code

```
#include <IRremote.h>

char buf[80];

int readline(int readch, char *buffer, int len) {
  static int pos = 0;
  int rpos;

  if (readch > 0) {
    switch (readch) {
      case '\r': // Ignore CR
        break;
      case '\n': // Return on new-line
        rpos = pos;
        pos = 0; // Reset position index ready for next time
        return rpos;
      default:
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
        }
    }
  }
  return 0;
}

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

IRsend irsend;

void loop() {
  if (readline(Serial.read(), buf, 80) > 0) {
    //tried to set up code to show what the arduino received and tried ways to send
    //Serial.print("You entered: >");
    //Serial.print(buf);
    //Serial.println("<");
    //doesn't seem to do anything irsend.sendNEC((uint32_t) buf, 32);
    //works but only for this one button irsend.sendNEC(0x210704FB, 32);
    //want to use irsend.sendNEC(buf, 32);
    //me trying to figure out what irsend is being fed through buf Serial.print((uint32_t) buf, 32);

  }
}

```

# Answer
> -1 votes
Same issue for me, but this is my solution.

Mapping beween python struct (packed data) and arduino struct is as follows:

```
Python              Arduino
?                   boolean
i                   int32_t or uint32_t
f                   float

```

Arduino Code:

```
// The struct we want to send over the serial connection
struct Data {
  int32_t timer;
  float value2;
  uint32_t sensor1;
  uint32_t datasize;
};
 Data data;
void setup() {
  // Initialize the serial connection
  Serial.begin(115200);
}

void loop() {
  // Create an instance of the Data struct

  data.timer = micros();
  data.value2 = 3.14;
  // read the input on analog pin 0:
  data.sensor1 = analogRead(A0);

  // Calculate the size of the struct in bytes
  size_t size = sizeof(data);
  data.datasize = size;
  // Allocate a buffer for the packed data
  uint8_t *buf = (uint8_t*)malloc(size);

  // Pack the data into the buffer
  memcpy(buf, &data, size);

  // Send the packed data over the serial connection
  Serial.write(buf, size);

  // Free the buffer
  free(buf);

  // Wait before sending the data again
  delay(10);

}

```

Python Code:

```
#
# read struct from arduino / sample code above
#

import serial
import struct

# Open the serial port
ser = serial.Serial('/dev/ttyUSB0', 115200)

# The struct we expect to receive from the Arduino
#struct Data {
#  int32_t value1;
#  float value2;
#  uint32_t value3;
#}
expFormat = "i f i i"         # Format to match arduino struct
structDataLength = struct.calcsize(expFormat)
print(structDataLength)       # RESULT IS 12

while True:
# Read the data from the serial port
# We read until we have received all the bytes for the struct

    data = b''
    while len(data) < structDataLength:
        data += ser.read(structDataLength - len(data))
    # Unpack the data into an instance of the Data struct
    val = struct.unpack('i f i i', data)

# Print the values
    print(val)

# Close the serial port
ser.close()

```

---
Tags: programming, c++
---


# Question
Title: Is it possible to program an AVR chip (atmega328p) via i2c?
Currently I am using `avrdude` and I'm programming my `atmega328p` chip via the `spi` pins by pulling the RESET pin low (spidev programmer).

In my project I'm using predominantly `i2c` and this the only place where `spi` is used. I was wondering whether it is possible to program the chip via the `i2c` protocol and remove the `spi` connections altogether?

My searches were unsuccessful.

# Answer
> 2 votes
From section 27.2(\*) of the Atmega328xx data sheet (emphasis mine):

> In ATmega88A/88PA/168A/168PA/328/328P the Boot Loader Support provides a real Read-While-Write Self- Programming mechanism for downloading and uploading program code by the MCU itself. This feature allows flexible application software updates controlled by the MCU using a Flash-resident Boot Loader program. **The Boot Loader program can use any available data interface and associated protocol to read code and write (program) that code into the Flash memory,** or read the code from the program memory. The program code within the Boot Loader section has the capability to write into the entire Flash, including the Boot Loader memory. The Boot Loader can thus even modify itself, and it can also erase itself from the code if the feature is not needed anymore. The size of the Boot Loader memory is configurable with fuses and the Boot Loader has two separate sets of Boot Lock bits which can be set independently. This gives the user a unique flexibility to select different levels of protection.

You may need to re-write the input section of the bootloader, but it sure sounds like Atmel intended it to be doable.

\[\*\] My data-sheet is dated 2018; the relevant section, Section 27, is titled "Boot Loader Support – Read-While-Write Self-Programming", in case a later revision has different section numbers.

# Answer
> 2 votes
Yes, as JRobert pointed out, I have no doubt - it is possible!

You need just 3 things:

1. a Bootloader that supports uploading the firmware via I2C
2. an Upload-Software that supports uploading the firmware to the bootloader mentioned in 1.)
3. an physical connection from the system the upload software is running on to the actual I2C bus of your device

Actually the physical interface is not the problem - there are USB\<\>I2C interfaces available widely, you can also re-use an arduino itself to be such.

Let's look at the bootloader.

Actually I found a german site that claims having a working I2C bootloader for Atmega8 including an upload tool (use Deepl.com to translate it). It may or may not work for other Atmegas as is.

There is also another project at github.

There will be more if you google for it. Actually I have not investigated any of them.

But chances are good than any of those might work for you.

---
Tags: i2c, atmega328, spi, linux, programmer
---


# Question
Title: SoftwareSerial will not read all of the printed string when calling readString()
I have an Arduino UNO and an ESP32 that need to communicate to each other using SoftwareSerial. The problem I am coming across is that when I call readString and print it out using Serial, it will not give me everything that has been printed out from my ESP32.

I have my Arduino RX Pin hooked up to 4 and TX hooked up to 5 I have my ESP32 RX2 Pin hooked up to 16 and TX2 pin hooked up to 17, with the GND hooked up to directly to the Arduino GND I am not using any resistors, straight up 5v of pure power

Arduino UNO Code:

```
// C-standard library
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <SoftwareSerial.h>

#define RX_PIN 4
#define TX_PIN 5

SoftwareSerial ardSerial(RX_PIN, TX_PIN);

void setup(void) {
  // Get access to network
  pinMode(RX_PIN, INPUT);
  pinMode(TX_PIN, OUTPUT);
  Serial.begin(9600);
  while(!Serial) {}
  ardSerial.begin(9600);
  while(!ardSerial) {}
}

void loop(void) {
  while (ardSerial.available() > 0) {
    String payload = ardSerial.readString();
    Serial.println(payload);
  }
  delay(1000);

}

```

ESP32 Code

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

#include <SoftwareSerial.h>

SoftwareSerial ardSerial;

void setup(void) {
  // Begin connections
  Serial.begin(115200);
  while (!Serial) {}

  ardSerial.begin(9600, SWSERIAL_8N1, RX2_PIN, TX2_PIN);
  while (!ardSerial) {}
  return;
}

void loop(void) {
  {
    String spotData = "Huge JSON File that needs transferred";
    ardSerial.print(spotData);
  }

  delay(5000);
}

```

Expected result:

* Able to retrieve every little bit of the JSON file that was printed out

Actual result:

* Only receive like half of the JSON file

# Answer
> 0 votes
I see 2 problems with your code:

* You wrote in the comments, that the JSON file is huge. The Uno has only 2kB of RAM and you are trying to lead the complete file into RAM at once. Such a JSON file from Spotify will easily exceed the 2kB (in fact you have even less, because the Arduino framework and SoftwareSerial also use some of the RAM). So you just cannot handle the complete file at once with an Uno.
* You use `readString()`. This function is sure easy, but also has some pitfalls. It uses the `String` class, which utilizes dynamic memory allocation. It allocates a bigger character array in RAM, if the current array is not big enough. That means, that you would need up to 2 versions of your String fitting into RAM while receiving, leaving only about 1kB. Also it will read from the SoftwareSerial interface, until a timeout is hit (1s by default I think). For building a robust communication between the two devices you should read until you reach a special character, for example via `readStringUntil()`. That special character is often the newline character `'\n'`.

**Possible solution:** First we should talk about the limited RAM problem. As stated above you cannot handle the full file at once. You need to handle it in chunks. Whatever you want to do with the data in the end, the Uno will need some time handling the current chunk of data. So you need to pause the transmission of data at the ESP, until the Uno is ready to receive more. Here you can go two ways:

* Send the data in chunks of predefined size (small enough for the Uno to hold at once in its RAM) and wait a predefined time between each chunk, that is long enough for the Uno to handle every data it might have gotten in that chunk. This is the easiest to program, but will necessarily take more execution time.
* Let the Uno signal to the ESP, that its buffer is full, for example by sending a special character to the ESP. The ESP should then stop sending, until it gets the OK from the Uno to proceed the transmission. To send without loosing data the Uno should probably also send the number of bytes received in that chunk. That way the ESP knows exactly, where in the data String the Uno is currently. This is a bit more difficult, though still easy enough and robust.

To handle the sending in chunks I would use the `write(const uint8_t *buffer, size_t size)` method of SoftwareSerial (actually this function comes from the `Print` class, from which `SoftwareSerial` inherits). The buffer is the pointer to the first element of the current chunk in the `char` array with the data. You can get the `char` array via `spotData.c_str()` and you can get the pointer to the n-th element of it via `&(spotData.c_str()[n])`. The second parameter is the size of the chunk in bytes. This needs to be small enough, that the data will fit into the RAM of the UNO, together with all the RAM needed for processing the data.

On the Uno I would then do the reading bytewise. Something like this:

```
char data[BUFFER_SIZE]="";
int pos=0;

void loop(){
    if(ardSerial.available()){
        data[pos] = ardSerial.read();
        if(pos == BUFFER_SIZE - 1){
            // Handle chunk of data
            pos = 0; // reset position to reuse buffer
        } else {
            pos++;
        }
    }
}

```

I have left out some parts to only demonstrate the principle. Also you need to define `BUFFER_SIZE` yourself, depending on the available RAM.

Obviously this does not implement the second option with the pause signal, which is more complex.

---

Apart from sending and receiving you will need to think about how to process the chunks of data. This depends largely on what exactly you want to do with that data. Just sending them via Serial is easy. Interpreting the data in chunks is more difficult.

# Answer
> 1 votes
There are two ways to implement a parser for a language like JSON or XML:

1. Have the parser swallow the whole document at once, and produce an in-memory representation of the same data.
2. Have the parser return control to the caller for each “event” it detects, where an “event” is typically a primitive data item, or the start or the end of a container.

Parsers of the first kind are much easier to use, but this can be expensive in RAM usage if you want to parse a alrge document. The second kind of parsers are harder to use, but they are able to parse huge documents using a minimal amount of memory.

On an Arduino, you would typically use ArduinoJson, which is a parser of the first kind, not ideal for parsing huge documents on little memory. A quick search for “event driven C++ JSON parser” got me JsonReader. I did not try it, and do not know whether that would work on Arduino, but it shows that at least this kind of parsers do exist for JSON in C++. You may want to search further along this way.

Before you dig into this, however, I suggest you give ArduinoJson a second chance. ArduinoJson has a couple of tricks that can help dealing with large documents:

* You can ask it to filter the data as it reads it, in order to only keep in memory the items you are actually interested in.
* You can deserialize in chunks, and use the data extracted from one chunk at a time.

Both techniques are explained in the tutorial How to deserialize a very large document?.

Also, let's not forget the obvious: you should not attempt to store the raw JSON document in memory. Instead, you should give ArduinoJson a reference to your stream (namely `ardSerial`), and let it directly pull the bytes as it parses.

---
Tags: arduino-uno, serial, esp32, atmega328, softwareserial
---


# Question
Title: Just installed Arduino 2.0.3 - what is windows path to associated libraries?
Just installed Arduino 2.0.3 and I attempted to build a sketch which includes a library that I manually installed in version 1.8.19 and it can't be found:

In my program I have `#include <DS3231.h>`

Now, attempting to compile it cannot find the library.

What is the path to the basic libraries in Arduino 2.0.3?

# Answer
I found the location by examining the app while it was running.

The associated libraries are at:

`%localappdata%\arduino15\Libraries`

That will look like : `C:\Users\<username>\AppData\Local\Arduino15\libraries`

I created a new folder named `DS3231` dropped in the .cpp, .h and .config files and now my sketch compiles with the `#include <DS3231.h>`

Kind of blows my mind that the Arduino 2.0.3 Libraries are found in a directory named Arduino15. Is that an old version or something?

Here's what I see in preferences -- don't see a location for user libraries:

The best location will be your sketchbook location + a folder named `libraries`.

For example, in my case my sketchbook location is :

`c:\users\<username>\dev\arduino`

so my library folder should be:

`c:\users\<username>\dev\arduino\libraries`
> 0 votes

---
Tags: arduino-ide, library, arduino-ide-2
---


title: Arduino nano timing precision

text:
# Question
Title: Arduino nano timing precision
How precisely can an Arduino nano be timed? The project I am working on needs two Arduino nano to work synchronously. Arduino one have to activate a relay after 2700 sec and Arduino two have to activate a second relay after 2700.360 sec (360 milli seconds after )

With the code given below the required accuracy is not achieved.

```
volatile uint32_t ovfCount = 0UL;
volatile uint32_t currentTime = 0UL;
volatile unsigned long time_prev = 0UL;
volatile unsigned long dT = 0UL;

unsigned long delayTime = 2700UL;     //Seconds
unsigned long coilActivateTime = 5UL;  // seconds

volatile unsigned long _waitTime = delayTime * 1000UL + 360UL;
uint32_t _burnTime = coilActivateTime * 1000UL;

volatile bool coilOn_flag = false;

ISR(INT0_vect) {

  EIMSK = 0b00000000;

  TCCR1B = B00011100;
  PORTB ^= (1<<0);
  ovfCount = 0;
  TIFR2 = 0;
  TCNT2 = 0;

}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(TIMER1_OVF_vect) {
  //pass
}

ISR(TIMER1_COMPA_vect) {
  //pass
}

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

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

  uint32_t totalCount = ovf_count << 8 | tcnt2;  // raw count
  // uint32_t currentTime = totalCount * 0.004;     // milli second
  currentTime = totalCount * 4UL/1000UL;  // milli second

  if (currentTime >= _waitTime) {
    PORTC ^= (1 << 5);   // relay Switch
    TCCR1A = B00000010;
    TIMSK1 = B00000101;
    PORTB |= (1<<1);
    if (coilOn_flag) {
      TCCR1B = 0;
      PORTB ^= (1 << 1) | (1<<0);
    }
    coilOn_flag = true;
    _waitTime = _burnTime;
    ovfCount = 0;
    TCNT2 = 0;
  }
}

void setup() {
  Serial.begin(115200);
  /*setting the pin directions*/
  DDRB |= (1 << 1) | (1 << 0); // gL, rL
  DDRC |= (1 << 5);  // relay
  DDRD &= B11111011; // interrupt- interrupt

  /* INITIAL STATE SETTING FOR THE PINS */
  PORTB &= B11111100; // rL, gL
  PORTC &= B11011111; // relay

  /* 8Bit Timer*/
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = B00000011;
  TCCR2B = B00001100;
  OCR2A = 250;
  TCNT2 = 0;
  TIFR2 = 0;
  TIMSK2 = B00000001;

  /* 16 bit timer */
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1A = B10000010;
  // TCCR1B = B00011100;
  TCCR1B = 0;
  ICR1 = 62461;
  OCR1A = 6206;
  OCR1B = 624;
  TCNT1 = 0;
  TIFR1 = 0;
  TIMSK1 = B00000111;

  /* External INTERRUPT */
  EICRA = 0b00000010;
  EIFR = 0;
  EIMSK = 0b00000001;

  PORTB ^= (1<<0);
}

void loop() {

}

```

How to correct the code.?

# Answer
The Arduino Nano is nowhere accurate enough for your application, and this has nothing to do with your code: it is a hardware limitation. 360 extra milliseconds after 2,700 seconds is a difference of only 133 ppm (parts per million). The Arduino Nano is clocked off a ceramic resonator, and these time sources carry a typical error of the order of 1,000 ppm. The best thing the code can do is count the clock cycles with perfect accuracy, which makes the software timing as good as the underlying hardware, but never better.

Some options you may try:

1. The one that seems most obvious is to have the first Arduino somehow send a trigger signal to the second one when it activates the first relay. Or have the second Arduino sense the state of that relay. Then, all the second Arduino has to do is wait for 360 ms, which it can easily do with reasonable accuracy.
2. If there is no way the Arduinos can communicate, then you could try to add external time sources to the Arduinos. Some RTC modules can output a 32,768 Hz signal that could be accurate enough for your needs. Look for a temperature-compensated RTC, as those are more accurate.
3. If you cannot add extra hardware, you could try to calibrate the clocks of your Arduinos in order to compensate for their relative drift. Keep in mind though that the drift rate is temperature-dependent, and wanders randomly even at constant temperature. First read the article Arduino clock frequency accuracy, by Joris\_VR, to get an idea of the accuracy you could expect from such calibration.
> 2 votes

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


# Question
Title: avrdude: usbdev_open(): cannot open device: Permission denied
I'm trying to upload anything to my Arduino Uno Wifi Rev2, I'm on Arch Linux, but I'm failing with the following error be it via IDEv2 or `arduino-cli`:

> avrdude: usbdev\_open(): cannot open device: Permission denied
>
> avrdude: jtag3\_open\_common(): Did not find any device matching VID 0x03eb and PID list: 0x2145

The device permissions:

```
crw-rw-rw- 166,0 root uucp  9 Jan 23:22 /dev/ttyACM0

```

My udev rule:

```
KERNEL=="ttyACM[0-9]",MODE="0666",GROUP="uucp",TAG+="uaccess"

```

`lsusb`:

```
Bus 001 Device 005: ID 03eb:2145 Atmel Corp. ATMEGA328P-XMINI (CDC ACM)

```

First two entries from `udevadm info -a -n /dev/ttyACM0`:

```
  looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1/tty/ttyACM0':
    KERNEL=="ttyACM0"
    SUBSYSTEM=="tty"
    DRIVER==""
    ATTR{power/control}=="auto"
    ATTR{power/runtime_active_time}=="0"
    ATTR{power/runtime_status}=="unsupported"
    ATTR{power/runtime_suspended_time}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1':
    KERNELS=="1-3:1.1"
    SUBSYSTEMS=="usb"
    DRIVERS=="cdc_acm"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="02"
    ATTRS{bInterfaceNumber}=="01"
    ATTRS{bInterfaceProtocol}=="01"
    ATTRS{bInterfaceSubClass}=="02"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{bmCapabilities}=="6"
    ATTRS{iad_bFirstInterface}=="01"
    ATTRS{iad_bFunctionClass}=="02"
    ATTRS{iad_bFunctionProtocol}=="01"
    ATTRS{iad_bFunctionSubClass}=="02"
    ATTRS{iad_bInterfaceCount}=="02"
    ATTRS{physical_location/dock}=="no"
    ATTRS{physical_location/horizontal_position}=="left"
    ATTRS{physical_location/lid}=="no"
    ATTRS{physical_location/panel}=="top"
    ATTRS{physical_location/vertical_position}=="upper"
    ATTRS{supports_autosuspend}=="1"

```

I feel like I've tried everything so far:

* `sudo chmod a+rw /dev/ttyACM0`
* `sudo usermod -a -G uucp $USER`
* adding udev rule with all different configs (although if chown/chmod doesn't work what will it change??)
* changing ownership to my user...
* I checked the process for the IDE to make sure it runs on my user and it does
* After all these steps I always either restarted and/or reloaded everything with `sudo udevadm control --reload-rules && sudo udevadm trigger`
* Went through plethora of similar topics, no clues

I feel like I must be doing something awfully stupid here, it doesn't make any sense to me why it wouldn't work even after I chown'ed it to my user...

# Answer
Looking at the board definition for the UNO WIFI R2, it doesn't use the serial port for upload. It's using an mdbg chip that it speaks to over a non-cdcacm USB protocol. Getting yourself into the group-owner for the serial device is good for communicating to the board through the serial monitor though.

The megaavr board package seems to come with a file for creating your udev rules that you should find at:

```
"${USER}/.arduino15/packages/arduino/hardware/megaavr/1.8.8/scripts/create_dfu_udev_rule"

```

The 1.8.8 subdirectory of megaavr is current as of writing. It will no doubt change. I still have 1.8.7 on my system.

Running it should create the necessary udev rule for allowing avrdude to speak directly to the USB device. Specifically they're adding this:

```
SUBSYSTEM=="usb", ATTR{idVendor}=="03eb", ATTR{idProduct}=="2145", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1"

```

They seem to be creating a udev rule for the tty device as well, though that shouldn't strictly be necessary given what you've already done with becoming a member of the serial device's group. Basically you're doing it by becoming a member of the owning group where what they did was just open the device up to RW permissions for everyone.
> 1 votes

---
Tags: linux, arduino-uno-wifi
---


title: Can't read through I2C from RTC

text:
# Question
Title: Can't read through I2C from RTC
I'm using an ESP32 which I connected to a MAX31329 RTC through I2C.

Unfortunately I can't read any register from the RTC. After modifying the MAX31328 library didn't work, I tried reading single registers directly. Here is the code:

```
#include "Wire.h"

int seconds = 0;
int ret = 0;

void setup() {

Serial.begin(115200);
delay(500);

Wire.begin(33,32,100000);

delay(500);
Wire.beginTransmission(0x68);
  Wire.write(0x06);
  Wire.write(13);
  ret = Wire.endTransmission();
  if(ret != 0)
    Serial.println("i2c Setup failed");

  delay(500);
}

void loop() {

  Wire.beginTransmission(0x68);
  Wire.write(0x06);

  Wire.requestFrom(0x68,1);
  seconds = Wire.read();
  ret = Wire.endTransmission();
  if(ret != 0)
    Serial.println("Read failed");

  Serial.println(seconds);

delay(1000);
}

```

The register always returns 0.

Do you see the error in my code? The datasheet of the MAX31329 can be found here.

I'm trying for days now and have no clue what the problem is. Thanks a lot for your support in advance.

Best regards,

Martin

# Answer
You are doing things in the wrong order.

> ```
>  Wire.beginTransmission(0x68);
>  Wire.write(0x06);
>  Wire.requestFrom(0x68,1);
>  seconds = Wire.read();
>  ret = Wire.endTransmission();
>
> ```

The request is sent on the endTransmission call, so you need to do that before trying to get a response. In other words:

```
  Wire.beginTransmission(0x68);
  Wire.write(0x06);
  ret = Wire.endTransmission();

  Wire.requestFrom(0x68,1);
  seconds = Wire.read();

```
> 1 votes

# Answer
To read the max31329 you do need to do the following as Nick Said

```
Wire.beginTransmission(0x68);
Wire.write(0x06);
ret = Wire.endTransmission(false); //No Stop, so the request is a restart

Wire.requestFrom(0x68,1);
seconds = Wire.read();

```

But it needs to be a repeated restart following the write to register 0x06, hence the false in Wire.endTransmission(false). It took me ages to figure out as the DS3231 and MAX31328 don't required this, I actually found this writen in the data sheet for the MAX31343 which has a similar set of registers with seconds starting at 0x06 unlike the previous clocks that start at 0x00. Interestingly with these ones, reading the status register 0x00 will return to you any flags for interupts and automatically reset them after reading the register, which I think is new and better.
> 1 votes

# Answer
I have been using the ESP32 for about 10 years now and it can be finicky

I2C is an Open Collector interface requiring Pull-up resistors to work.

If you are using a board module it likely has the pull-ups if not make sure you have them (around 1.5K OHMS) from SDA and SCL to 3.3 Vcc.

I suggest starting with Arduino's i2cdetect.ino and debug if it is being seen.
If not you have a wiring issue.

while both other answers are fairly good, you show no schematic or mention if you are using a RTC board.
> 0 votes

---
Tags: i2c, esp32, rtc
---


# Question
Title: Wire.write invalid conversion from ‘char*’ to ‘const uint8_t*
I have written this code:

```
char message[4];
memcpy(message, &delta, 4);

Wire.write(message, 4);

```

When I try to compile I get this warning:

```
warning: invalid conversion from ‘char*’ to ‘const uint8_t* {aka const unsigned char*}’ [-fpermissive]
   Wire.write(message, 4);
                        ^

```

Also followed by this note:

```
In file included from main.ino:5:0:
/usr/share/arduino/libraries/Wire/Wire.h:61:20: note:   initializing argument 1 of ‘virtual size_t TwoWire::write(const uint8_t*, size_t)’
     virtual size_t write(const uint8_t *, size_t);
                    ^

```

I do not understand what is wrong?

# Answer
Try

```
Wire.write((const uint8_t*) message, 4);

```

I.e., cast it to the correct type, uint8\_t and char are the same (at least on Arduino and for this example, as you do not char about unsigned/signed values).

(see also the comment of the busybee below, for using the cleaner C++ cast).
> 1 votes

---
Tags: arduino-uno, data-type, wire-library
---


# Question
Title: No SPIFFS data upload in Arduino IDE 2.0.0-rc3 (ESP32 & TTGO) - Ubuntu
I tried adding ***esp32fs.jar*** to ***/home/myname/Arduino/tools/ESP32FS/tool*** (and a few other places as it looked likely that the jar file wasn't loading). I've definitely got the correct board selected, and can upload Sketches. I can also run the demo that writes to SPIFFS.

But the Tools menu doesn't have an option for ***ESP32 Sketch data upload***.

Is SPIFFS data upload not available so far in V2?

# Answer
> 1 votes
FS upload plugins for ESP are not available in IDE 2 yet (2022-01-07).

IDE 2.0 doesn't run on Java so it can't use the java plugins of the IDE 1. You have to use IDE 1 for FS upload and exception decoder until new plugins are written for IDE 2.

It is tracked here: https://github.com/arduino/arduino-ide/issues/58

# Answer
> 3 votes
I've created a utility that provides a web-based ESP32 interface for

* OTA
* File system formatting
* FS directory listing
* File uploading
* File editing
* File deletion

It can be found at https://github.com/palmerr23/ESP32-OTA-and-File-Manager

---
Tags: esp32, spiffs, arduino-ide-2
---


# Question
Title: How to send multiple bytes with Wire without copying
When I need to send multiple bytes via Wire, for example a long int, I cast it to a byte array and specify a length

```
long int i;
Wire.write((byte*)&i, 4);

```

But if I want to send bytes from more than 1 variable I need to create a buffer

```
byte i;
byte j;
byte message[2] = {i, j};
Wire.write(message, 2);

```

If I want to send them without copying the data I can put them in a struct

```
struct message {
  byte i;
  byte j;
};
Wire.write((byte*)&message, 2);

```

But this would require me to refactor existing code.

Is there any c voodoo that I can perform to send bytes of different places of my code over Wire without copying them in a buffer and without refactoring the code?

# Answer
No, this function overwrite of `Wire.write()` is meant for buffers, meaning connected spaces in memory, which can be covered by simply incrementing the buffer. That is not the case for distinct variables.

But that begs the question, why you want to do that in one call to `Wire.write()` in the first place. This function does **not** do any communication on the I2C lines, it just **writes to the libraries internal buffer**. The data gets actually send in `Wire.endTransmission()` or in the onRequest interrupts in the background (depending on where you have those write statements). Thus you already have a buffer and don't need another one. Just call `Wire.write()` multiple times, once for each variable. That will build up the data sequentially inside the internal buffer.
> 4 votes

# Answer
```
// Written by Nick Gammon
// May 2012

template <typename T> unsigned int I2C_writeAnything (const T& value)
  {
  Wire.write((byte *) &value, sizeof (value));
  return sizeof (value);
  }  // end of I2C_writeAnything

template <typename T> unsigned int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything

```

Then in the body of your code you can:

```
I2C_writeAnything(message);

```

Similarly your other end can `I2C_readAnything`.

There is a small amount of refactoring required, changing the function call.
> 1 votes

# Answer
No, you cannot.

C does not guarantee any allocation properties of variables. Even if you write one variable definition right after another, both variables can have addresses assigned that have other memory in between.

So, if you want a "packet" sent via `Wire` that contains values of multiple variables, you need to fill a buffer with these values.

Even though C maintains the order of members of a structure, please be aware that depending on the target's architecture there can be gaps between the members for alignment. However, some compilers have language extensions to tackle this issue.
> 1 votes

# Answer
As @chrisl said, there is an internal buffer so the best I can do is just use multiple `Wire.write` calls, but in my case that wasn't working. I got only the last written value or rubbish data.

I dug through the source of the Wire library and found that the version in github (as of this writing) makes it possible to use multiple writes by appending to the buffer:

```
// set length and copy data into tx buffer
for(i = 0; i < length; ++i){
  twi_txBuffer[twi_txBufferLength+i] = data[i];
}
twi_txBufferLength += length;

```

But the one I have installed locally looks like this:

```
// set length and copy data into tx buffer
twi_txBufferLength = length;
for(i = 0; i < length; ++i){
  twi_txBuffer[i] = data[i];
}

```

So that explains a lot.

In case someone else also has this problem, you just need to update.

I was even too lazy to update, so I just replaced the function. Probably not the best decision, but it works!

Thanks!
> 1 votes

---
Tags: c, data-type, pointer
---


title: How to increase pinout switching?

text:
# Question
Title: How to increase pinout switching?
Consider this code:

```
void loop() {
    digitalWrite(pinTest, HIGH);
    digitalWrite(pinTest, LOW);
}

```

On an Arduino Mega 2560, running 16MHz (=0.06us), I would expect the width of the pulse to be somewhere around 0.1us.

However, when measuring with my oscilloscope, I get around 4us high and 5-6 us low. I understand it could take some cycles to run the `digitalWrite` code, but this seems quite a lot.

How is that difference explained?

# Answer
> 3 votes
You do not need to go all the way down to assembly in order to get that speed. You can do direct port access from your `.ino` file:

```
void setup() {
    DDRA |= _BV(PA0);  // pin 22 = PA0 as output
    for (;;) {
        PINA |= _BV(PA0);  // toggle PA0
    }
}

void loop(){}

```

This compiles to something that is almost equivalent to your assembly code. Actually, it is a bit faster, as it uses `rjmp` instead of the slower `jmp` instruction.

**Edit**: A few notes

1. As pointed out by timemage in a comment, you can save another CPU cycle by writing `PINA =` instead of `PINA |=`.
2. This code, as well as your two examples, will exhibit a glitch every 1,024 µs. This is caused by the periodic timer interrupt used by the Arduino core for timekeeping (`millis()`, `micros()` and `delay()`). You can avoid the glitch by disabling interrupts before going into the tight loop. Alternatively, if you do not use the Arduino core at all, you can define a function called `main()` instead of `setup()` and `loop()`: this will completely remove the Arduino core initialization for your compiled program.
3. `arduino-cli` is useful for sparing you the complexity of the Arduino build system (automatic installation of the cores and libraries, libraries in multiple places that depend on the core you use...). If you do not use the Arduino core, `arduino-cli` is of little use: a very simple Makefile that calls `avr-gcc` and `avrdude` is all you need for basic AVR development.

# Answer
> 0 votes
I fixed it by using assembly code to run the program. Because I am using Linux, I couldn't use Atmel Studio, but you can easily use AVR assembly with `arduino-cli`.

Make your `.ino` like this:

```
extern "C" void myAssemblyMain();

void setup() {
    myAssemblyMain();
}
void loop() {
}

```

then add a `pulse.S` file with the assembly code:

```
#define __SFR_OFFSET 0

#include "avr/io.h"

.global myAssemblyMain

myAssemblyMain:
  sbi   DDRA, 0     ; Set PA0 as output

blink:
  sbi   PINA, 0     ; Toggle PINB
  jmp   blink

```

Using this code, I get a ~400ns pulse. Which is more than enough for my needs.

---
Tags: digital, speed, digitalwrite
---


title: Will Nodemcu support 4AAA

text:
# Question
Title: Will Nodemcu support 4AAA
Will Nodemcu support 4AAA batteries which is 6v approx, or should i go with 3AAA batteries which is 4.5V approx. And one more question , is it ok to use AA instead of AAA ?

# Answer
Yes, yes and yes.

> Will Nodemcu support 4AAA batteries which is 6v approx

Yes, it will. However there is no back-powering protection on the USB, so having that connected whilst the board is connected to your computer could potentially damage your computer's USB port. That's why VIN's label was changed to 5V on the newer boards.

> or should i go with 3AAA batteries which is 4.5V approx.

Yes, you should. Not only does that mean your USB port won't die, but you're not wasting as much power. The NodeMCU employs a linear "LDO" regulator to get 3.3V from the incoming power source. That means that the voltage difference between incoming power and 3.3V is thrown away as heat. The higher the incoming voltage the more heat is generated to discard that voltage. Using a lower voltage, therefore, means that you don't waste as much. That fourth battery is doing absolutely nothing towards powering your project and is just being used to generate more heat. One thing to note though is that 5V coming in from USB could try and charge your 3xAAA batteries. If they're not rechargeable then they could cause problems (overheat, leak, cause a fire, etc). Adding a schottky diode in series with them would protect them from that.

> is it ok to use AA instead of AAA ?

Yes. Your project will last longer before you need to replace the batteries, since AA batteries have a higher mAh capacity than AAA.
> 2 votes

# Answer
You don't have to connect any UART. This is done through USB serial communication. So, just copy the uf2 file to pico. Let it reboot. Then you should see a ttyS\* or ttyACM\* device shows up in /dev/ if PX4 is running fine. Then you can connect to it using putty or minicom.
> -1 votes

---
Tags: nodemcu, battery, voltage
---


title: Recognizing fake NEO-M8N gps module?

text:
# Question
Title: Recognizing fake NEO-M8N gps module?
I bout a NEO-M8N gps module but I can't connect to u-blox softwares (both u-center2 & u-center\_v22.07)

It seems to be one of the junk modules that China mass-produces

Module's pictures :

I tried **TinyGPSPlus**, **Sparkfun u-blox** and some other libraries to connect it to my **ESP32 Dev. Board (30 pin board)** but i cant programme it, Also i connected to my laptop USB port directly but i even can't see it coming up to my device manager list (not even as unknow device) All i can see is the onboard LED turning On when i connect it

Is there any **Arduino sketch** to recognise it (recognise it's core) to find it's library? Or is there any **free windows software** to recognise all gps modules? And then, how can i programme it to connect esp32 and give me lat, long & alt as float numbers?

**Note :** i have **ESP32 Dev. Kit (30 pin)** as my only controller so, any suggestion sketch must be compatible with the board

# Answer
> -1 votes
just plug the unit to terminal software, set the baud to 9600 and see what is coming out.

you can even use Arduino IDE, if the unit is not faulty, you should be able to see data coming out.

I use Neo8M & Neo6M, all bought from AliXpress, not a single failed so far.

---
Tags: esp32, gps
---


# Question
Title: Why does Serial.write() work but Serial.print() doesn't?
I am testing my GPS module with an ESP32 using the Arduino IDE. I'm asking because I usually don't fully understand the difference between `Serial.write()` and `Serial.print()`.

This code is working perfectly with `Serial.write()` and the output is meaningful:

```
void loop() {
  while (Serial2.available() > 0) {
    Serial.write(Serial2.read());
  }

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

```

Output:

```
13:28:05.173 -> -------------------------------------
13:28:05.206 -> $GPRMC,,V,,,,,,,,,,N*53
13:28:05.238 -> $GPVTG,,,,,,,,,N*30
13:28:05.238 -> $GPGGA,,,,,,0,00,99.99,,,,,,*48
13:28:05.270 -> $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
13:28:05.334 -> $GPGSV,1,1,00*79
13:28:05.334 -> $GPGLL,,,,,,V,N*64
13:28:05.366 -> -------------------------------------

```

When I convert this code to `Serial.print()` the output looks strange:

```
void loop() {
  while (Serial2.available() > 0) {
    Serial.print(String(Serial2.read()));
  }

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

```

Output:

```
13:26:43.118 -> -------------------------------------
13:26:43.150 -> -------------------------------------
13:26:43.214 -> 367180827767444486444444444444444444447842535113103671808684714444444444444444447842514813103671807171654444444444444844484844575746575744444444444442525613103671807183654465444944444444444444444444444444575746575744575746575744575746575742514813103671807183864449444944484842555713103671807176764444444444448644784254521310-------------------------------------
13:26:43.566 -> -------------------------------------
13:26:43.629 -> -------------------------------------

```

Why does `Serial.write` work, but `Serial.print` doesn't? Or: how to write the same code with `Serial.print()`?

# Answer
> 2 votes
> Why does Serial.write work, but Serial.print doesn't?

`Serial.read()` returns an integer for each byte from the serial port.

`String` converts each integer to its decimal ASCII representation (e.g. $ = "36", G = "71" etc), so `Serial.print()` receives an ASCII string with the decimal values of each input byte, which were already ASCII. This is probably not what you want.

# Answer
> -1 votes
> Well, @devnull gave a good and helpfull answer. I'll present another method of using Arduino to test the GPS module.

Here is an example of test code that you can use to test a GPS module with an ESP32 using the Arduino IDE and the `Serial.print()` function:

```
#include <TinyGPS++.h>
#include <HardwareSerial.h>

// Set up a serial connection for the GPS module
HardwareSerial GPSSerial(2);
TinyGPSPlus gps;

void setup() {
  // Initialize serial communication with the computer
  Serial.begin(115200);

  // Initialize serial communication with the GPS module
  GPSSerial.begin(9600, SERIAL_8N1, 16, 17);
}

void loop() {
  // Read data from the GPS module
  while (GPSSerial.available() > 0) {
    gps.encode(GPSSerial.read());
  }

  // Print the GPS data to the serial monitor
  Serial.print("Latitude: ");
  Serial.print(gps.location.lat(), 6);
  Serial.print(" Longitude: ");
  Serial.println(gps.location.lng(), 6);
  Serial.print("Altitude: ");
  Serial.print(gps.altitude.meters());
  Serial.println(" meters");
  Serial.print("Date: ");
  Serial.print(gps.date.month());
  Serial.print("/");
  Serial.print(gps.date.day());
  Serial.print("/");
  Serial.println(gps.date.year());
  Serial.print("Time: ");
  Serial.print(gps.time.hour());
  Serial.print(":");
  Serial.print(gps.time.minute());
  Serial.print(":");
  Serial.println(gps.time.second());
  Serial.println();

  // Wait a second before printing the data again
  delay(1000);
}

```

This code initializes a serial connection with the GPS module using the HardwareSerial library and the TinyGPS++ library to parse the GPS data. The `loop()` function reads data from the GPS module and prints the latitude, longitude, altitude, date, and time to the serial monitor using the `Serial.print()` function.

You may need to adjust the serial port and baud rate settings to match your specific GPS module. You may also want to add additional code to handle errors or check for valid GPS data.

# Answer
> -1 votes
i only use this to get data from the GPS module, no need for library you need to declare an array, say gps\_rawData\[200\] = {0};

while (SerialGPS.available()) { size\_t byteCount = SerialGPS.readBytesUntil('\n', gps\_rawData, sizeof(gps\_rawData) - 1); gps\_rawData\[byteCount\] = NULL; String gps\_rawDataString = String(gps\_rawData); SerialMon.println(gps\_rawDataString); }

this way you have the data in an array to be manipulated whenever or wherever required.

---
Tags: serial, esp32
---


# Question
Title: Powering Arduino and transistors with one power supply > 12V
So say you want to use transistors with your Arduino Nano to power components, which require greater than 12V. If your power supply is more than 12V, is there a way to safely use the same power supply to power the Arduino?

# Answer
> 1 votes
The voltage regulator (on the Vin pin) is supposed to be provided with 12V at max, since it is not cooled (it is a linear regulator, that dissipates the excess voltage as heat). If you have significantly more, you should at best buy a little switching regulator, to directly get a regulated 5V to feed to the 5V pin of the Arduino (that's what I suggest). Be sure to use a regulator, that can provide the needed current (which also depends on what else you provide over the Arduino).

If you really don't want to use an extra regulator and you don't have much more than 12V (maybe like 15V), you might get away by cooling the voltage regulator on the Arduino. The voltage regulator on a genuine Arduino will go into emergency shutdown, if it overheats, but it will not be damaged easily. Here you could try a bit. But be careful to not stress it too much. The clones from china often have different/cheaper regulators, that will mostly be fried if you overheat them. But they are very cheap.

# Answer
> 1 votes
The recommended input voltage for the Arduino Nano is 7-12 V, the max. 20 V.

So you could use upto 20 V, but this is indeed not advisable.

What you can do, is to use a so-called step down/boost down converter which converts the voltage back to a voltage that your Arduino Nano can (easily) handle. The voltage drop will be changed into heat, but I guess considering you are using a higher voltage power supply, you are not using battery power.

Note: this is only true for some (cheap?) converters, see the comment of DataFiddler below.

# Answer
> 0 votes
If I understand your question you have external devices say lamp, motor, etc. There are several ways of doing it. My preferred way is to use a N-Channel MOSFET where the drain is the output, the source is ground (both the logic and power grounds need to be connected together) and the gate Is connected to the port pin that also has a 10K pull down resistor. You can use the 12V to power the Arduino via Vin as you suggested. Be sure the MOSFET is avalanche rated and will turn on at about 3V or less.

You can do the same thing with an NPN Transistor where the port pin connects to the base with a 300 Ohm resistor (you need to calculate this based on the load), emitter to the connected grounds and the collector is your output.

---
Tags: power
---


# Question
Title: Adafruit_LEDBackpack library interfering with analog input reading
I'm trying to do something I think would be simple. I'd like to read the input of a electret microphone board and update the Adafruit 24-segment LED Bar Graph. I got each individual item working perfectly: I can read the input of the microphone on the analog pin and I can update the LED bar graph using I2C.

The issue occurs when I tried to combine the two concepts. When the bard graph gets updated, the analog input reads HIGH (1023) and never changes. I used my standard debug method and commented out code until the problem went away, so I've narrowed down the issue to a single line of code (right at the end). When the bar.writeDisplay is called the analog input perpetually reads 1023.

If I comment out that one line of code and re-upload my sketch the readings (in the Serial Monitor) are as expected (lower when its quiet and higher when its loud).

Under the hood Adafruit is using the Wire library.

I'm no good at wiring diagrams, but here's what I have:

RoboDyn Mega 2560 Pro (Embed) 5V, Gnd, SDA (20), SCL (21) to the LED Backpack 5V, Gnd, Out (A15/69)

That said, I'm relatively confident this is not a wiring problem as everything works until the software gets ahold of it.

```
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

Adafruit_24bargraph bar = Adafruit_24bargraph();

int pin = 69;
unsigned int sampleWindow = 50; // millis
unsigned int maxScale = 24;

void setup() {
  Serial.begin(9600);
  bar.begin(0x70);  // pass in the address
}

void loop() {
  unsigned long startMillis = millis();  // Start of sample window
  unsigned int peakToPeak = 0;   // peak-to-peak level
  unsigned int sample;
  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;
  while (millis() - startMillis < sampleWindow) {
    sample = analogRead(pin);
    if (sample < 1024) {  // toss out spurious readings
      if (sample > signalMax) {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin) {
        signalMin = sample;  // save just the min levels
      }
    }
  }
  peakToPeak = signalMax - signalMin;
  int displayPeak = map(peakToPeak, 0, 1023, 0, maxScale); // map 1v p-p level to the max scale of the display
  Serial.print("mic: "); Serial.print(peakToPeak); Serial.print(" "); Serial.println(displayPeak);
  for (uint8_t b = 0; b < 24; b++) {
    if (b <= displayPeak) {
      int c = LED_GREEN;
      if (b >= 20) {
        c = LED_RED;
      }
      else if (b >= 16) {
        c = LED_YELLOW;
      }
      bar.setBar(23 - b, c);
    }
    else {
      bar.setBar(23 - b, LED_OFF);
    }
    //bar.writeDisplay(); // <------- THIS LINE
  }
}

```

UPDATE: It appears to be something with the way Adafruit uses the Wire library. I have a similar problem when I use the Adafruit 7-segment library, when I use their MCP23017 library.

But it is wiring related too. If I uncomment the commented out line above but disconnect the I2C device the analog input starts working again.

One more thing I've discovered: it depends on how many lights are lit on the I2C board. Once all the lights are lit, the analog pin reads full. When only a couple of lights are lit, the values are lower. It is like the voltage going into the mic is higher when the lights are brighter.

For curiosity sake, I tried the same thing on a different Arduino (Adafruit Feather 32u4) with the same result (so it isn't my Arduino).

# Answer
Since you cannot post a schematic I will take a SWAG and say you have two different hardware devices using the same pin for different reasons. I2C is a bus only and its associated pins cannot be used for anything else. Be sure the I2C bus is only connected to I2C terminals. Also be sure it is terminated properly.
> 0 votes

---
Tags: adafruit, atmega2560, wire-library
---


# Question
Title: Arduino ESP32 Import Error No module named serial
I googled and couldn't find a solution to my nice problem: I have Ubuntu and I want to program a ESP32 ............... I tried a lot of pip commands ... but it didnt work. You have any idea how to install the correct packages? Maybe you can tell me what to do. I am really lost. I tried it last year and also failed.. Now I want to try it another time :)

```
   /.arduino15/packages/esp32/tools/esptool_py/3.0.0/esptool.py", line 38, in <module>
        import serial
    ImportError: No module named serial

```

# Answer
Open terminal and enter this command `python -m pip install pyserial` it will download `pyserial` for you and you will not receive the above error. The above error is because you don't have `pyserial` installed on the system.

The related documentation for pyserial could be found here
> 9 votes

# Answer
I had the same issue compiling the CameraWebServer example. I'm using Ubuntu 20.04. The problem occurs during the linking stage when the script invokes python. On my system this runs the system python which is python 2.7.18. I don't think the serial module (supplied by pyserial) is available on Ubuntu 20.04 for python 2.x.

My solution was first to abandon the Arduino IDE and use the arduino-cli to compile the example. I created a virtual python 3 environment, activated it, installed pyserial under the virtual environment and run arduino-cli to make the runtime. The python scripts appear to be compatible with python 3.
> 3 votes

# Answer
Problem resolved, Thank you. I had installed pyserial. The error surprisingly was related to the incorrect processor speed (!) in the Arduino IDE. I have no idea why that would influence the serial/pyserial function.
> 1 votes

# Answer
Reference: https://www.how2shout.com/linux/how-to-install-python-2-7-on-ubuntu-20-04-lts/

I think Arduino IDE expects Python2 to be installed. My Version is Arduino-1.8.13 You also need Python2 modules so you need to install pip2

:~/curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py :~/sudo python2 get-pip.py :~/pip2 install pytools :~/pip2 install pyserial
> 1 votes

---
Tags: esp32
---


# Question
Title: How does Arduino handle passing this union?
I'm unsure how this will be handled by the Arduino compiler. If anyone can explain what and why, I'd appreciate it. This is obviously very simplified, but it does contain the actual issue.

At the module level I have this `union`. I understand that this is strictly speaking not correct C++, but it does work for me, at least when used directly and not passed as a argument to a function.

```
  union _TAT {          // access as bytes or uint32
    uint32_t wide = 0;
    uint8_t bytes[4];
  };

  _TAT oneTAT;        // a variable of _TAT

```

Suppose I also have a function that works on these:

```
  void fix_Term(_TAT atat) {
    atat.wide = 0;
    atat.bytes[3] = 17;
  }

```

...and I invoke it with:

```
  fix_Term(oneTAT);

```

As I understand it, passing `AnArray[]` is equivalent to passing `*AnArray`, so the function might/should see `atat.bytes[3]` as a pointer to that byte of the variable. But what about `atat.wide`? I haven't explicitly passed `oneTAT` by reference, so...?

What might actually happen here? It does compile without complaint but I can't test it because the hardware it depends on isn't available yet. Besides, even if it works, I'd like to know why.

And of course, if it's just wrong, how do I best accomplish passing and modifying a variable like this?

# Answer
It is confusing in C and C++ that arrays are passed as pointers but an instance of class, struct or union is always passed by value (so as a copy) including the arrays which are part of the memory space of the structure as in the case of your union.

If you want to pass by reference, declare the function's parameter as a reference 'type'. For example `void fix_Term(_TAT& atat) {`.
> 2 votes

# Answer
Yes passing `AnArray[]` is equivalent to passing `*AnArray`. **But** declaring `uint8_t *anarray1` is *not* equivalent to declaring `uint8_t anarray2[4]` in a struct/class/union definition. The former includes a pointer to a byte in the struct, the later actually includes 4 bytes in the struct. So in the later case, `anarray2` already points to data, and using `variable.anarray2[0]` correctly gets you the value in the structure, while calling `variable.anarray1[0]` would result in undefined behavior, because the pointer just points anywhere.

So your code is compiling and executing without error, but since you're passing the union by value, the effect of your `fix_term` function is discarded, much like if you had passed in an ordinary value type instead (such as int).
> 2 votes

---
Tags: programming, c++
---


title: Arduino Output Panel Font Color Change

text:
# Question
Title: Arduino Output Panel Font Color Change
I am using Arduino IDE 2.0.3. When compiling code if there is an error it shows on a black background with a red font, that is hard for me to read. Can I change either the background or the font? Looking within the IDE I don't see how and not seeing anything on the internet. TIA

# Answer
Thank you dankeboy36 for pointing out "Themes". Fixed it right up.
> 0 votes

---
Tags: ide, error, arduino-ide-2
---


# Question
Title: Can an ethernet shield function as an adapter?
I want to communicate with my Arduino over a long distance so I decided to use an Ethernet cable between my computer and Arduino. Searching up a few tutorials I've found them all mentioning IP addresses and establishing a network.

Simply put my question is can an Ethernet shield make the Arduino function basically the same as with a direct USB connection into its port(with Serial and all) without having to establish a network/other things. If so, is it as simple as saying something like "Ethernet.begin()" and then continuing?

Thank you, and please note that I (clearly) do not have much TCP/IP experience (but am more than willing to learn).

# Answer
No, you cannot do that. Ethernet is *very* different from a serial link. You will have to deal with IP addresses, port numbers, the notions of client and server, and so on. Note that, once you manage to establish a TCP connection through Ethernet, *that connection* does behave pretty much like a (somewhat virtualized) serial link. But you have to establish the connection first. So you will have to study a bit, read documentations, etc.

Alternatively, if you only need a short-distance link (say, a couple of km), you can try RS-485 instead of Ethernet. RS-485 is a physical layer commonly used to transmit regular serial data. From the software point of view, it is pretty much a regular serial link, save for the fact that you usually cannot speak and listen at the same time (you could, with more expensive cabling).
> 1 votes

---
Tags: serial, usb, ethernet-shield
---


# Question
Title: Using multiple ultrasonic sensors simultanously with the same trigger
I want to use three ultrasonic sensors together and would prefer to use as few pins as possible, so I was thinking of using one trigger for all 3 sensors. The sensors will have an angle of 90 degrees between them. I was wondering if this would still cause false readings? Since they are a large angle (and some distance) apart?

# Answer
I was looking into this a while back using HC-SR04 sensors and did have some issues with bad (well, strange) readings. but I was just fiddling around with it and haven't gone back to it.

That being said, if you connect the triggers together, but the echo lines individually, and put at least 60ms delay between triggering and reading each sensor, then it might work for your application.

This thread briefly touches on how the time it takes for a ping to decay is part of the issue. https://forum.arduino.cc/t/multiple-ultrasonic-sensors-close-together/410358

My understanding of it suggests that if you send out a ping in multiple directions, the ping going right echoes off a surface, then echoes off a surface on the left side, which returns to the sensor on the other side, so the sensor might receive a lot of noise.

The datasheet on the HC-SR04 indicates that the cycle time of a single measurement should be 60ms, so a trigger signal doesn't align with an echo... https://forum.arduino.cc/uploads/short-url/961oW5W0LoHZ6t5XOP40HryBlZK.pdf

In any case, these sensors are cheap and I find that throwing a few bits on a proto board and testing experimenting with them is the best way to learn.

Start with two sensors opposing each other with a surface at 2 inches in front of one, and at 4 inches from the other. trigger them together, see if you can get a clean read from either one. Experiment with different distances to objects (like within an inch on each side, etc). Then repeat the process with a third at the front, and with surface objects at odd angles.

I hope this is helpful, if not encouraging at least :)
> 1 votes

---
Tags: sensors
---


# Question
Title: Can an Arduino and an NI USB-6009 DAQ board interfere with each other's signals when they are simultaneously reading signals from different sensors?
Hello dear Arduino SE community.

I have 5 sensors. I read 4 of them with an NI USB-6009 DAQ board and I read the fifth one with an Arduino UNO R3. Though, with the fifth sensor not only I read a signal from it, but I also send a signal to it.

Both the Arduino and the NI board are connected to a computer via two different USB ports and send the signals to the computer simultaneously. Also - simultaneously - the Arduino sends a signal to the fifth sensor.

I noticed a strange behavior with the signal from one of the sensors read by the NI board. It starts with giving me a signal that is clearly wrong and over the course of, approximately, 5 minutes gradually changes to a correct reading.

That hadn't happened when I didn't have Arduino connected to the computer at the same time.

Thus, I'm wondering if it is possible that an Arduino and an NI board can interfere with each other's signals when connected to the computer simultaneously. If it is possible, is it something widespread and is there a working solution?

Thank you in advance. Ivan

P.S. I deliberately don't provide the specs of my system because the point of my question is not to resolve the issue but to learn if what I described is possible theoretically and if such cases have been encountered.

# Answer
I have found a solution to my problem.

The sensor that was giving me the wrong signal was plugged to the same electrical circuit with "heavy" equipment (two DC laboratory power supplies). It is well known that one shouldn't do it because "heavy" equipment sends noise back to the circuit which, ultimately, causes noise in the signal generated by the sensor.

Thus, my issue had nothing to do with the Arduino interfering with the USB-6009 through the computer.

To make sure, I disconnected the Arduino from the computer and still got the same wrong signal from the problematic sensor. Then, I plugged the problematic sensor to another electrical circuit, connected the Arduino back to the computer and got the right signal.

Thus, I conclude that one can safely use an Arduino and a USB-6009 with the same computer.
> 0 votes

---
Tags: communication
---


# Question
Title: Why are ATTiny so expensive compared to ESP modules compared to features they offer?
I was looking for a cheap MCU solution for a project, apart from being compact, ATTiny doesn't seem to provide much value. I was hoping it is cheaper but nope, They are mostly above 1.5 USD in any shop. Whereas I can easily get an ESP module for a comparable price if not cheaper, added WiFi, and optionally Bluetooth, and they are not too huge for my use cases. Am I missing something?

# Answer
You can get ATTINYs for much less than $1.50.

For example, right now you can order the ATTINY202 from stock in single unit quantiles from Microchip for $0.48 each. They drop to $0.35 each at 5K units (also in stock).

https://www.microchipdirect.com/product/search/all/ATTINY202

If you are really price sensitive then you can sometimes get the smaller ATTINYs for even less when buying in reels at a time, but you have to shop around.

Anytime you pick a part you have to trade-off purchase price, availability (both now and in the future), and suitability. The AVR parts can often be the best choice- but all depends on what you are using it for!
> 2 votes

---
Tags: attiny
---


# Question
Title: CH340K - Unknown USB Device (Device Descriptor Request failed)
I have a Arduino Nano clone working fine with the CH340 drivers. It has a CH340C on it.

I made a custom PCB. CH340 chips are hard to come by these days, so I opted for the CH340K, From the datasheet, seems like it should work similar to the CH340C and CH340G that are quite common.

My PCB has a footprint for both the CH340K and CH340C/CH340G (Yes, I'm aware I'm missing the load capacitors for the CH340G). CH340C/N/K/E and CH340B have built-in clocks without external crystal oscillator. So no need for a crystal.

After soldering on the CH340K and USB port, I plugged the device in, and I'm getting an error in Windows 10 Device Manager:

> Unknown USB Device (Device Descriptor Request failed)
>
> Windows has stopped this device because it has reported problems. (Code 43)
>
> The USB set address request failed.

I've uninstalled and reinstalled the CH340 drivers several times. Tried to force the driver onto the device in device manager, and it didn't let me.

There's no short to ground or vcc.

Any help to get this recognized would be great! thanks!

**CH340K Pinout**

**PCB**

# Answer
> 1 votes
Needed a 100nf capacitor on the v3 pin, per Majenko's suggestion, and per datasheet.

I thought this was only needed if you were going to use the 3.3v output for other purposes. I was wrong!

Same requirement for the CH340C!

# Answer
> -1 votes
on you Pcb the Footprint is not correct! UD+ is on GND, UD- is on UD+ and GND is on UD- . The CH340K has a differnt Footprint.

---
Tags: windows, ch340
---


# Question
Title: WebSocketsServer.h: No such file or directory
I'm trying use the NodeMCU WebSocket.

I downloaded the required libraries from: https://github.com/Links2004/arduinoWebSockets and pasted them in my Arduino libraries folder. I uploaded my code but got this error:

**WebSocketsServer.h: No such file or directory.**

*Can you please tell me why my Arduino IDE won't find the WebSocketsServer.h header file when it is physically present in my Arduino libraries folder? Or if there's an alternative way to use the NodeMCU WebSocket?*

Here's the code:

```
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WebSocketsServer.h>
#include <Hash.h>

// Replace with your network credentials
const char* ssid = "<WiFi-SSID>";
const char* password = "WiFi-PASSWORD";

WebSocketsServer webSocket = WebSocketsServer(81);
ESP8266WebServer server(80);   //instantiate server at port 80 (http port)

String page = "";
int LEDPin = D5;

void setup(void){
 //the HTML of the web page
 page = "<h1>Simple NodeMCU Web Server</h1><p><a href=\"LEDOn\"><button>ON</button></a> <a href=\"LEDOff\"><button>OFF</button></a></p>";
 //make the LED pin output and initially turned off
 pinMode(LEDPin, OUTPUT);
 digitalWrite(LEDPin, LOW);

 delay(1000);

 Serial.begin(115200);
 WiFi.begin(ssid, password); //begin WiFi connection
 Serial.println("");

 // Wait for connection
 while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
 }

 Serial.println("");
 Serial.print("Connected to ");
 Serial.println(ssid);
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());

 server.on("/", [](){
    server.send(200, "text/html", page);
 });

 server.on("/LEDOn", [](){
    server.send(200, "text/html", page);
    digitalWrite(LEDPin, HIGH);
    delay(1000);
 });

 server.on("/LEDOff", [](){
    server.send(200, "text/html", page);
    digitalWrite(LEDPin, LOW);
    delay(1000);
 });

 server.begin();
 webSocket.begin();
 webSocket.onEvent(webSocketEvent);

 Serial.println("Web server started!");
}

void loop(void){
  webSocket.loop();
  server.handleClient();
  if (Serial.available() > 0){
    char c[] = {(char)Serial.read()};
    webSocket.broadcastTXT(c, sizeof(c));
  }
}

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length){
  if (type == WStype_TEXT){
   for(int i = 0; i < length; i++) Serial.print((char) payload[i]);
   Serial.println();
  }
}
~~~

```

# Answer
> 1 votes
after you included the zip file to library you must rename directory like this 'WebSocketsServer'. And then you copy all file in 'src' directory and then paste them to its parent directory (WebSocketsServer)

# Answer
> 0 votes
The proper way is to add library into your Arduino IDE, it will **just work**.

1. Open the Arduino IDE
2. Go to `Sketch` \> `Include Library` \> `Manage Libraries`
3. Search for "WebSockets Sattler' and install the library named "WebSockets by Markus Sattler"
4. Restart the Arduino IDE.

PS

* you will see two results for WebSockets library from the same author
* the second "WebSockets\_Generic" is a more lightweight library and it only provides support for WebSockets in the client mode (it is designed to be more memory efficient)

# Answer
> -1 votes
proper way would be to add `WebSocketsServer.h` to list of locations that gcc looks for. see: https://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp\_1.html#SEC6

another way would be to download `WebSocketsServer.zip` from https://www.arduinolibraries.info/libraries/web-sockets to your workdir and unzip it

replace

```
#include <WebSocketsServer.h>

```

with explicit location

```
#include "./WebSockets-2.3.5/src/WebSocketsServer.h"

```

(note unziped version in this case is WebSockets-2.3.5)

---
Tags: arduino-ide, wifi, nodemcu, web-server
---


# Question
Title: Cannot communicate with software serial on particular devices (SIM7600G-H)
I have 3 devices:

* An UNO (non-genuine)

---

I'm using the UNO to talk to the SMS device via UART at `9600` baud to send and receive SMS commands. I need the hardware port open to debug, and I am trying to use a software port to talk to the SMS device via it's TX RX pins.

But I cannot get the software port to talk to the SMS device at all.

This is the success I've had trying to talk to and from devices. The bold boxes are needed to be solved for this setup to work. ✅ = working coms, ❌ = nothing on coms at all. Read left to right, **HAT serial (SMS DEVICE)** can communicate with UNO hardware serial.

And I'm using this code to just relay inputs and outputs between the hardware and software ports for testing.

```
// Must be same on mock and serial
const int baud = 9600;

// Communication with mock hat
SoftwareSerial mockPort(2, 3);

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

  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  mockPort.begin(baud);
  Serial.println("Mock port has started @ " + String(baud));
}

void loop()
{

  while (mockPort.available() > 0)
  {
    char inByte = mockPort.read();
    // and send to the hardware serial port:
    Serial.write(inByte);
  }

  // while there is data coming in FROM SERIAL, read it and send it back to mock
  while (Serial.available() > 0)
  {
    char inByte = Serial.read();
    // and send to the mock serial port:
    mockPort.write(inByte);
  }
}

```

Why can't I communicate to the SMS device with the software ports? (or the USB UART as well?) When testing, I can see the UNO's RX light turn on, but I never receive any data back from the SMS device (the serial monitor is just black).

---

Notes:

* I've tried the AltSoftSerial library as well
* I've set the SMS hat's baud rate default to `9600`
* I've tried different communication pins
* I've got the TX pins on RX pins and vice versa

# Answer
The `TX` and `RX` labels mirror the Raspberry Pi. So I swapped the `RX` and `TX` wires to connect as `RX`-\>`RX` and `TX`-\>`TX` and now it works
> 0 votes

---
Tags: serial, softwareserial
---


# Question
Title: Water pump controlled by soil moisture sensor
I'm just learning to code in Arduino.

The purpose is that first the sensor measures the moist level (I mapped the reading values from 0 to 100). If the value is less than threshold 70, then it will turn on a water pump. As soon as the value goes beyond 70, the pump stops pumping water.

The problem is that even when the value is less than 70, the pump doesn't work.

I tried replacing the pump with a LED, it turns on a the right moment. I tested the pump itself, and it also works perfectly.

```
//for mapping values
int mostMoist = 100;
int leastMoist = 600;
int percent;

//direct value from sensor
int raw;

//threshold for minimum percentage to turn on pump
const int threshold = 70;

//initial state of water pump
bool dosomething = false;

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

void loop() {
  //if it's not pumping water:
  while (dosomething == false){
  //check sensor value, map out of 100, and display on monitor
  raw = analogRead(A0);
  percent = map(raw,leastMoist,mostMoist,0,100);
  if (percent < 0){
    percent = 0;
  }
  Serial.println(percent);
  Serial.println("dosomething is set to false");

  //check if percentage moist is less than threshold. if so, set dosomething true, orelse, loop dosomething false
  if (percent<threshold){
    dosomething = true;
  } else{
    dosomething = false;
  }
  delay(2);
  }

  //if it's pumping water:
  while (dosomething==true){
  //check sensor value, map out of 100, and display on monitor
  raw = analogRead(A0);
  percent = map(raw,leastMoist,mostMoist,0,100);
  if (percent < 0){
    percent = 0;
  }
  //turn on pump
  digitalWrite(13,HIGH);
  Serial.println("dosomething is set to true");
  //check if percent moist is less than threshold value, if so, loop dosomething true, orelse, set dosomething false
    if (percent<threshold){
    dosomething = true;
  } else{
    dosomething = false;
  }
    Serial.println(percent);
  delay(2);
  }

}

```

# Answer
> 3 votes
I don't see a second power-supply in your photo. If you're trying to run the pump directly from an Arduino pin, it is highly likely that the pump needs way more current than the pin can supply.

It may be possible to power the motor from the USB but 1) the Uno board doesn't make that readily available, 2) it puts your PC at some risk (of back-EMF or of over-drawing the port's capability. But the ideal would be a separate power supply (don't forget to connect that supply's ground to the Uno's ground).

Also, if you tested the pump while dry it may have been able to run, yet with water in it, have been unable pull enough starting current to get going.

# Answer
> 0 votes
To control the pump you will need either a transistor or a relay board to handle the current. The arduinos pins can only drive 20 mA which is not enough for most pumps, even very small ones.

If the pump can run on 5 V and with \<400 mA a transistor (FET) may suffice an power could come from VCC or so. Otherwise an extra supply with a relay is one simple solution.

You could start here for instance.

Look for tutorials, there are so many out there to be found with search engine, it's worth :)

---
Tags: arduino-uno, sensors
---


# Question
Title: Arudino receiving interrupt command BEFORE entering sleep mode causing it not to receive any interrupt commands in order to wake up
I've written code for an Arduino Nano that when a button is pressed, it sends an IR command. It is set so that if no button press has been received for a period of 10 seconds, it will enter sleep mode until a button press is received. The button to send the IR command is the same button being used to send the wake up interrupt (button connected to pin D2). When testing the code the Arduino is able to go to sleep and wake up from the interrupt 1-3 times before it will suddenly receive an interrupt signal just before entering sleep mode. When this happens it gets stuck in sleep mode and will no longer accept the wake up interrupt. I am currently using Serial Monitor outputs and the built-in LED to determine when the Arduino is in sleep mode or not.

```
#include <IRLib.h>
#include <avr/sleep.h>
#define interruptPin 2

IRsend My_Sender;

const int button = 2;
int buttonState = 0;
int timeSinceCommand = 0;
const unsigned long eventInterval = 1000;
unsigned long previousTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);         //delete once code finalized and working
  pinMode(interruptPin, INPUT_PULLUP);
  digitalWrite(LED_BUILTIN, HIGH);      //delete once code finalized and working
  Serial.println("---------------------------New Run---------------------------");
}

void loop() {
  while (timeSinceCommand < 10) {
    unsigned long currentTime = millis();
    buttonState = digitalRead(button);
    if (buttonState == HIGH) {
      My_Sender.send(SONY, 0xC90, 12);
      timeSinceCommand = 0;
      previousTime = currentTime;
    }
    if (currentTime - previousTime >= eventInterval) {
      timeSinceCommand++;
      previousTime = currentTime;
    }
  }
  if (timeSinceCommand >= 10) {
    Going_To_Sleep();
    timeSinceCommand = 0;
  }
}

void Going_To_Sleep() {
  sleep_enable();
  attachInterrupt(0, wakeUp, RISING);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  digitalWrite(LED_BUILTIN, LOW);             //delete once code finalized and working
  Serial.println("Arudino going to sleep!");  //delete once code finalized and working
  delay(1000);                                //delete once code finalized and working
  sleep_cpu();
  Serial.println("Arudino has waken up!");    //delete once code finalized and working
  digitalWrite(LED_BUILTIN, HIGH);            //delete once code finalized and working
}

void wakeUp() {
  Serial.println("Interrupt received!");      //delete once code finalized and working
  sleep_disable();
  detachInterrupt(0);
}

```

Here is the Serial Monitor output from a couple of tests:

```
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!

```

# Answer
> 2 votes
There are a couple of tricky things going on here... First, you should be aware of a few facts:

1. Buttons are prone to mechanical bounce. You press a button once, and quite often the microcontroller senses multiple transitions on the input pin.
2. When INT0 is configured to sense rising edges, any rising edge on the pin will set the INTF0 interrupt flag, *whether the interrupt is enabled or not*. Once the flag is set, it will fire an interrupt request as soon as the interrupt is enabled.
3. When the CPU receives an interrupt request, it finishes executing the current instruction before servicing the request.

With that in mind, here is an explanation of what goes on:

When you wake up the Arduino with the push button, it often triggers multiple signal transitions. The first rising edge wakes up the Arduino and triggers the interrupt. The second rising edge only sets the INTF0 interrupt flag: the interrupt is “on hold”, because interrupts are not themselves interruptible. However, before exiting, `wakeUp()` disables servicing that interrupt, which means the flags just stays set. It is a pending interrupt of sorts.

Some time later, `Going_To_Sleep()` is called again. `attachInterrupt()` enables the interrupt and, since the flag is still set, the (pending) interrupt fires immediately. That's when you see the message “Interrupt received!” printed right before the Arduino goes to sleep. The problem is that the interrupt is disabled by `wakeUp()`. One second later, `sleep_cpu()` puts the CPU to sleep, and now our wake-up source is disabled, so the Arduino is just locked into its dreams.

There is still one issue with this scenario. The interrupt handler supposedly disabled sleeping, so how come the Arduino went to sleep anyway? The answer is that sleeping was accidentally re-enabled by `set_sleep_mode()` because of a data-race. Here is a disassembly of `set_sleep_mode()`:

```
in   r24, 0x33 ; read SMCR (Sleep Mode Control Register) into r24
andi r24, 0xF1 ; clear the Sleep Mode Select bits
ori  r24, 0x04 ; select the Power Down mode
out  0x33, r24 ; write back SMCR

```

The first instruction in this sequence comes right after the instruction in `attachInterrupt()` that enables the INT0 interrupt. When that instruction generates an interrupt request (because the interrupt flag was already set), the interrupt request reaches the CPU while it is already executing the `in` instruction above, and this instruction is completed before servicing the interrupt request. This means that we have now in register r24 a copy of the Sleep Mode Control Register from before the interrupt is serviced. In this copy, the SE bit (Sleep Enable) is set. Even though `wakeUp()` clears that bit in the actual SMCR register, it stays set in our copy in r24. Then, the `out` instruction re-enables sleeping. I experimented putting a single `nop` instruction right before `set_sleep_mode()` and that was enough to prevent the data race.

So here you have an explanation of the observed behavior. I may come up with some suggestions for fixing the problem, but it need to take some sleep before that (do not worry, I will make double sure I have one interrupt source enabled before executing `sleep`).

# Answer
> 1 votes
I'm taking this opportunity to include a simple basic sleep sketch which eliminates the possible race condition risk that Edgar Bonet identified in the standard approach to using the sleep mode for AVR class MCUs. See the reference in the sketch to further optimise, if required, to switch off the ADC, Brown out detection etc.

```
/*
   Sleep mode demonstration (Uno/Nano ATmega328P)
   based on https://www.gammon.com.au/power Sketch J
   but stripped down for demonstration purposes to exclude some optimisation (BOD and ADC etc.)
   See also: https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

   Connect a button switch between pin 2 and ground
   Press the button. It wakes, blinks the led and then sleeps.

*/

#include <avr/sleep.h>

const byte LED = 13;  // built in led

void wake()
{
  // nothing here. All done in the loop
}

void setup()
{
  Serial.begin( 115200 ) ;
  pinMode( LED, OUTPUT );
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt ( digitalPinToInterrupt(2), wake, FALLING);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
}

void loop()
{
  Serial.println( "waking . . . ") ;

  // your own code could go here instead

  for ( int i = 0; i < 4; i++ ) {
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    delay (50);
  }
  delay(3000) ;

  Serial.println( "Sleeping. . . " ) ;
  Serial.flush() ;
  delay(20) ; // allow message to be written

  sleep_mode();
  // *** we wake here ***
}

```

---
Tags: arduino-nano, interrupt, timers, sleep
---


# Question
Title: Clarification of power-up behaviour of MAX7219 display driver
What is the exact meaning of the Initial Power-Up Section of the MAX7219 data sheet to be found on Page 7?

It says:

> On initial power-up, all control registers are reset, the display is blanked, and the MAX7219/MAX7221 enter shutdown mode. Program the display driver prior to display use. Otherwise, it will initially be set to scan one digit, it will not decode data in the data registers, and the intensity register will be set to its minimum value.

Most of this is clear. But specifically, what does the "the display is blanked" mean? Does it mean that the MAX7219 internal SRAM is cleared as part of the power-up sequence or does it mean that because the display is set to shutdown mode by power-up the display will be blank.

I have sought widely and cannot find a definitive statement. Which of these interpretations is correct, or perhaps is there another interpretation?

Why does it matter? Idle curiosity really. My read of the datasheet was that the RAM was cleared and hence did not expect to have to manually clear it.

So I didn't, and was wondering where the flash of random data at power up in my bank of displays was coming from, prior to the first display data write. And I was a bit too slow in accepting I got reading the datasheet wrong, or the datasheet didn't apply to the clone I was using.

I was wondering if someone had a definitive answer from some deep investigation or perhaps insider information. It seems not, and it may not be consistent anyway.

For the clone MAX7219s in my collection, the SRAM is not cleared on power-up. I don't know if that is the case for genuine MAX7219 or for different clones for that matter. In future, I will just assume not and zero out the SRAM manually.

That point about a pull-up resistor on the chip select(CS) line to mitigate erratic behaviour is an excellent one. Random noise here can easily generate unexpected results.

It should be noted though that if the CS line is not the default Slave Select (SS) of the SPI pin group, it is not enough to use a pull-up resistor alone.

The SPI begin function takes care of the case that the default SS pin will glitch low as it is made an output if the corresponding bit in the output register is not set to 1 prior to setting the pin to output mode.

For the default SS pin, begin() does a digitalWrite HIGH first, setting the internal pullup resistor on (and the output register bit to 1) then a pinMode to OUTPUT, thus if the SS pin is already pulled high by a resistor there are no glitches.

However, if the CS pin is a pin other than the designated SS, then the same process must be undertaken by user code. If forgotten, even a pulled up pin will glitch low as the output register, with the bit set to 0, is transferred through to the pin when it is configured as output.

It is easily fixed using the same method as the SPI library uses, digitalWrite a HIGH to the CS pin, then set that pin to OUTPUT. And pull it up, of course.

# Answer
I think it's pretty clear from the datasheet.

> all control registers are reset

The digit displays are registers, and therefore they will contain zeroes.

Displaying one digit, being in shutdown mode, and minimum intensity are all what would happen if all registers were set to zero.

> I have sought widely and cannot find a definitive statement.

Why is this important to know? When powered on it will be blank, as stated. Presumably you will configure it to the way you want it before leaving shutdown mode.
> -1 votes

---
Tags: max7219, startup
---


# Question
Title: Direct port manipulation takes 300 nanoseconds to execute for some reason
I have this code

```
#include <Arduino.h>

void setup() {

  DDRD  = B00001000;

}
void delayNanoSeconds(int time){
    int ans = (float)time / 62.5;
    for(int i = 0; i < ans; i++){
        _NOP();

    }

}
#define delay250 _NOP(); _NOP();_NOP(); _NOP();
#define delay1000 delay250 delay250 delay250 delay250
void loop() {
  while(1){
       PORTD ^= B00001000;
       delay1000; delay1000;
  }

  }

```

but I am getting delay of 2300 us here is a picture of the logic analyzer  and when I change delay to 250 or 1000 I am still getting this extra 300ns so why

# Answer
Remember: every single thing the CPU does takes time. Here is a disassembly of your `loop()`:

```
    ldi  r25, 0b00001000 ; r25 = B00001000
1:  in   r24, PORTD      ; r24 = PORTD
    eor  r24, r25        ; r24 ^= r25
    out  PORTD, r24      ; PORTD = r24
    nop
    nop
    ...
    nop
    rjmp 1b              ; goto previous label 1

```

As you see, besides your series of `nop`, there are four instructions in the loop:

* `in`, `eor` and `out` take one cycle each
* `rjmp` takes two cycles.

That is a total overhead of 5 CPU cycles, or 312.5 ns when running at 16 MHz. Pretty close to what you are seeing.

If you want an exact timings, you will have to disassemble your code and count the overhead cycles, as I did here. Then, I suggest this simpler approach:

```
#define OVERHEAD_CYCLES 5

void loop() {
    for (;;) {
        PORTD ^= _BV(PD3);
        _delay_us(2 - OVERHEAD_CYCLES / (F_CPU / 1e6));
    }
}

```
> 6 votes

---
Tags: arduino-uno
---