body:
I have an acceleration sensor (**ADXL355**) that returns 20-bit data in three bytes, formatted as **2s complement** :

 - acc3 (bits 19-12) in byte register 3 (mapped to bits 7-0)
 - acc2 (bits 11-4) in byte register 2 (mapped to bits 7-0)
 - acc1 (bits 3-0) in byte register 1 (mapped to bits 7-4 while 3-0 are unused)

the acceleration value is taken as a signed 32 bit integer from the above 3 registers as follows :

    int32_t acc32 = ((uint32_t)acc3 << 12) | ((uint16_t)acc2 << 4) | (acc1 >> 4);

    if (acc32 & (1UL << 19)) acc32 -= 1UL << 20;

Then, I am doing some statistical analysis on acceleration values to calculate an offset trim as a signed 32 bit integer.

    int32 off32;

This offset has to be written back to sensor as a 16 bit 2s complement value as follows :

- offset high byte (bits 15-8)
- offset low byte (bits 7-0)

The datasheet says that "***The significance of offset bits 15-0 matches the significance of acceleration bits 19-4***".

I found this rather tricky so I am asking how to convert this signed 32 bit offset integer to a 16 bit offset integer that follows the above specification.

I had this idea but don't know whether it is correct :

    int16_t off16[i] = (int16_t)(off32[i] / 16);

    sendSPI((uint8_t)(off16 >> 8));
    sendSPI((uint8_t)off16);

Any comment should be greatly appreciated !

title: How to process 20-bit sensor data

Answers: 1

body:
Other than the subscript `[i]`, which looks suspicious, what you did
seems perfectly correct to me. Now, if I go nitpicking, I may suggest:

- use a bit shift, as it is way cheaper than a division
- round to nearest, rather than towards zero or minus infinity.

This gives:

```c++
int16_t off16 = (off32 + 8) >> 4;
```

Note that the bit shift behaves like a division that rounds towards −∞
(regular division rounds towards zero). Adding 8 achieves
round-to-nearest, with ties rounded up.


body:
I'm just trying to connect my Adruino to internet and my Ethernet connection config code fails when I try to verify it, and I'm not sure what is the exact reason.

I'm using an Ethernet shield and have installed Ethernet v.2.0.0 library.

This is the running code:
```
WANStatus initialiseWAN() {
  // Enter a MAC address for your controller below.
  // Newer Ethernet shields have a MAC address printed on a sticker on the shield
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  WANStatus res;

  Serial.println("[INFO]: Initialising WAN");
  // Try to initialise Ethernet connecion

  if (Ethernet.begin(mac) == 0) {
    res.error = true;
    res.retry = true;

    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      res.message = "Ethernet shield was not found";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }

    // If all component are present try assigning a static IP address
    IPAddress ip(192, 168, 0, 177);
    IPAddress myDns(192, 168, 0, 1);
    Ethernet.begin(mac, ip, myDns)
    Serial.print("[INFO]: Assigned static IP: "); Serial.println(Ethernet.localIP());

    if (Ethernet.linkStatus() == LinkOFF) {
      res.message = "Ethernet cable is not connected";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }
    if (Ethernet.linkStatus() == Unknown) {
      res.message = "Ethernet link status is 'Unknown' check the cable";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }

//    Static IP assigned
    res.error = false;
    res.retry = false;
    res.message = "Static IP Address";
    return res;
  } else {
//    Received IP address from DHCP
    Serial.print("[INFO]: Received DHCP IP: "); Serial.println(Ethernet.localIP());
    res.error = false;
    res.retry = false;
    res.message = "DHCP IP Address";
    return res;
  }

//  ToDo: check WiFi modules here
}
```

And, the error message:

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/9TZ9k.png
```
[Starting] Verifying sketch 'controller\controller.ino'
[Warning] Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README.
Loading configuration...
Initialising packages...
Preparing boards...
Verifying...
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:8:0:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp: In member function 'uint16_t DNSClient::BuildRequest(const char*)':
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\utility/w5100.h:457:25: warning: result of '(256 << 8)' requires 18 bits to represent, but 'int' only has 16 bits [-Wshift-overflow=]
#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) )
                      ~~~^~~
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:164:18: note: in expansion of macro 'htons'
twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
^~~~~
Sketch uses 22574 bytes (69%) of program storage space. Maximum is 32256 bytes.
Global variables use 1467 bytes (71%) of dynamic memory, leaving 581 bytes for local variables. Maximum is 2048 bytes.
IntelliSense configuration already up to date. To manually rebuild your IntelliSense configuration run "Ctrl+Alt+I"
[Done] Verifying sketch 'controller\controller.ino'
```

title: Ethernet library compilation error

Answers: 1

body:
Everything is alright. There is no compiler error and your sketch is ready to upload.

The compiler warning "*result of '(256 << 8)' requires 18 bits to represent, but 'int' only has 16 bits*" from the Ethernet library source code is nothing you have to worry about.


body:
This code is quoted from [here][1]. May I know how to increase the speed of the NEMA 17 stepper motor further? I tried to increase the step speed to 2000rpm but it does not even work. It only works for less than 300rpm in my case.  The max rpm of the Nema 17 should be 5000rpm I googled. I used a 20V power supply lithium ion battery on the L298N motor driver. How do I solve this problem so that the Nema 17 can be faster? I believe the problem its with the code.

Thank you for reading and have a nice day :)

----------

    #include <Stepper.h>

    const int stepsPerRevolution = 100;  // change this to fit the number of steps per revolution
    // for your motor

    // initialize the stepper library on pins 8 through 11:
    Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

    void setup() {
      // set the speed at 60 rpm:
      myStepper.setSpeed(300);
      // initialize the serial port:
      Serial.begin(9600);
    }

    void loop() {
      // step one revolution  in one direction:
      Serial.println("clockwise");
      myStepper.step(stepsPerRevolution);
      //delay(500);
    }

  [1]: https://www.youtube.com/watch?v=cYTICj4DWYc&t=1036s&ab_channel=Robojax

title: Nema 17 stepper motor speed problem

Answers: 0


body: When using the AccelStepper library to control the motor, I need the current position of the motor at any given time when in motion. However, the functions in this library blocks so `currentPosition()` cannot return the position until the `move()/run()` function blocks completely to the desired/set position. How can I circumvent this to move and display the position simultaneously?

title: AccelStepper motor current position

Answers: 0


body:
My code represents a water level sensor, and the components are the Arduino Uno, a breadboard, an ultrasonic servo and two LEDS in which one is red and the other is green.

The condition that I don't know how to include in my code properly to make the servo rotate and activate the LEDs simultaneously:

When the distance is <= 50, servo rotates 180 and activates the red LED
else
servo goes to zero and activates the green LED.

My code:

````
#include <Servo.h>
int position = 0;
Servo srv;

const int trigPin = 4;
const int echoPin = 2;
const int ServoPin = 3;
const int green = 5;
const int red = 6;

int durantion;
int distance;

// **************************************//
void setup()
{

 Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(green, OUTPUT);
  pinMode(red, OUTPUT);
  srv.attach(ServoPin);

}

void loop() {

  int duration, distance;
  pinMode(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
 distance = pulseIn(echoPin, HIGH);
 distance = duration *30/2500;

  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

 if (distance <= 50)

{
  digitalWrite(red, HIGH);
  srv.write(180);
   delay(1000);
}
else
{
  digitalWrite(green, LOW);
  delay(1000);
  srv.write(0);
}
}

```

[![System][1]][1]

  [1]: https://i.stack.imgur.com/6YXgf.png

title: What is my code lacking that the servo rotates non-stoppingly? Servo should rotate 180 when distance is <= 50 and 0 when this condition is not true

Answers: 1

body:
Checking your program I found two errors IMHO. Please see the comments in the copied code below. The one also pointed out by @EdgarBonet definitely prevents your program from working correctly. The other one only has impact of the correctness if the values of the constants OUTPUT and LOW differ. I don't know if that is the case.

I'm pretty sure, that the continously turning servo is not caused by the program. There are two kinds of servos. One type that gets a signal which indicates the angle of the turn of the servos arms. The other type gets the same signal (called PWM = Pulse Width Modulation) and interprets it as the speed with that it continously turns the servo arms.

If you use the latter one the arduino sends a signal like turn about 180° but the servo understands turn with full speed. There is nothing you can do programatically to avoid that.

There are workarounds like build a feedback loop with a potentiometer that measures the angle of the turn or use stopper sensors.
But the simplest way is to use a servo that is made for your usecase. (A non continous or standard servo for e.g. RC Cars, RC Ships, RC Air Planes)

BTW: The picture your provided shows a simulation. If the Servo in the simulator turns continuously, perhaps there is a property you can use to change the servo type from continuous to standard. ??

    #include <Servo.h>

    int position = 0;
    Servo srv;

    const int trigPin = 4;
    const int echoPin = 2;
    const int ServoPin = 3;
    const int green = 5;
    const int red = 6;

    int durantion;
    int distance;

    void setup()
    {
      Serial.begin(9600);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
      pinMode(green, OUTPUT);
      pinMode(red, OUTPUT);
      srv.attach(ServoPin);
    }

    void loop()
    {

      int duration, distance;
      // error: you already set the pinmode to OUTPUT
      // pinMode(trigPin, LOW);
      // perhaps you mean
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      // error: duration or distance ? ;-)
      // distance = pulseIn(echoPin, HIGH);
      duration = pulseIn(echoPin, HIGH);
      distance = duration * 30 /2500;

      Serial.print("Distance: ");
      Serial.print(distance);
      Serial.println(" cm");

      if (distance <= 50)
      {
        digitalWrite(red, HIGH);
        srv.write(180);
        // improvement: delay necessary?
        // delay(1000);
      }
      else
      {
        digitalWrite(green, LOW);
        // improvement: delay necessary?
        // delay(1000);
        srv.write(0);
      }
    }


body:
Yesterday, I've got myself an arduino uno. Since I'm pretty newbie in it, I'd like to ask here for a hint, because I can't manage to make my "calculator" working. I don't have much experience in programming, but I thought, the loop should wait for one of the function called to end, instead of it, it looks like it is running all function, over again, and probably that's why I getting error in console output.

Code:

      #include <Key.h>
    #include <Keypad.h>

    const byte rows = 4;
    const byte columns = 4;

    char first_number;

    char keyboard[rows][columns] = {
        {'1','2','3','+'},
        {'4','5','6','-'},
        {'7','8','9','/'},
        {'C','0','=','*'}
      };

    byte  rowsPins[rows] = {9, 8, 7, 6};
    byte columnsPins[columns] = {5, 4, 3, 2};

    Keypad keys = Keypad(makeKeymap(keyboard), rowsPins, columnsPins, rows, columns);

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

    int getNumber(){
        char user_input = keys.getKey();
        int value;

        if (user_input){
        switch (user_input){
              case '0':
                value = 0;
                break;
              case '1':
                value = 1;
                break;
              case '2':
                value = 2;
                break;
              case '3':
                value = 3;
                break;
              case '4':
                value = 4;
                break;
              case '5':
                value = 5;
                break;
              case '6':
                value = 6;
                break;
              case '7':
                value = 7;
                break;
              case '8':
                value = 8;
                break;
              case '9':
                value = 9;
                break;
              default:
                Serial.print("Error int");
        }
      }
      return value;
    }

    int calculate(int first_number, int second_number){
        char operation = keys.getKey();
        int value;

        switch(operation){
            case '+':
              value = first_number+second_number;
              break;
            case '-':
              value = first_number-second_number;
              break;
            case '*':
              value = first_number*second_number;
              break;
            case '/':
              value = first_number/second_number;
              break;
            default:
              Serial.println("Error cal");
          }
          if (value){
              Serial.println(value);
            }
         return value;
      }

    void loop(){

      int first_number = getNumber();
      int second_number = getNumber();
      int test = calculate(first_number, second_number);
    }

What I wanted to do, is read numeric input from the keypad twice (it's just for now. I know it should be done different), and then, input the operation, such as multiply, but since the loop calling the function all over again, I can't actually do it. How I should approach it?

title: Can't manage my calculator to work

Answers: 1

body:
Consider this excerpt from your code:

```c++
int getNumber() {
    char user_input = keys.getKey();
    int value;
    if (user_input) {
        // ...
    }
    return value;
}
```

Think about what would happen if the condition `if (user_input)` turns
out to be false. The function would simply return an uninitialized
variable, which contains basically garbage.

The method `getKey()` from the Keypad library is intentionally
_non-blocking_. It returns immediately in order to avoid the rest of
your program being stuck while waiting for keypad input. If some key is
pressed, the method returns that key. Otherwise it returns `NO_KEY`,
which is zero and, as a boolean, evaluates to false. This means that,
when no key is pressed, the function `getNumber()` returns immediately,
and it returns garbage.

The correct approach would probably involve some sort of [finite state
machine][fsm]. However, for this simple example you can get away with a
quick-and-dirty solution: block while waiting for user input:

```c++
// Wait for user input.
do {
    user_input = keys.getKey();
} while (!user_input);
```

Keep in mind though that, if your program is going to evolve, at some
point the blocking approach can become an issue, and you may have to
completely rewrite the logic in a non-blocking fashion.

[fsm]: https://majenko.co.uk/blog/finite-state-machine


body:
I have a fancy setup to cool my beer at a controlled temperature (you can find details and a photo [here][1] if you want). The input of my system is a temperature, the output is a servo position.

**Long story short**

On startup the servo is stable enough, but every time after 67s of runtime suddenly the servo starts vibrating. I have an oscilloscope and I can see that after 67s, instead of a steady 2.3 ms the length of the pulses oscillate in a small range, like between 2.300 and 2.320 ms, and it's enough of a range to be a problem.

What happens at 67s ?? Is there some kind of overflow ? I'm very puzzled because all in all my code for the pulse is very simple.

I'm having my problem on [this code][2], branch bs18b20 of my repo. The pulse is generated line 293, with custom code.

**More context**

I had already asked for help [right here][3] with my setup. We had determined that using Servo.h along along with the 1Wire protocol make the interruptions used by both libraries get in the way of one another, so the servo receives bad values and vibrates too. In my last comment in this thread I said that the problem was solved, but I discovered later the problem of the servo getting unstable after some time, as exposed above.

To overcome that I changed tactics, switched my bs18b20 for a lm35 which doesn't need 1Wire, and switched back to Servo.h. It worked very well... in my electronics lab. But then (reality sucks) I found out when actually using my device in the kitchen that sometimes the temperatures start getting very wrong, and I suspect that the humidity alters the voltage reading of my lm35. And that's why I'm trying to change back again to my previous solution with a waterproof bs18b20.

While writing this, stackexchange proposed [this thread][4] with a very promising solution, I will definitely try that. Nonetheless, for the sake of it, I'm still interested in knowing what causes my problem above, so I'm posting this anyway.

  [1]: https://gitlab.com/guillaume.deshors/brewing_thermometer
  [2]: https://gitlab.com/guillaume.deshors/brewing_thermometer/-/blob/bs18b20/thermometre/thermometre.ino
  [3]: https://arduino.stackexchange.com/questions/80700/arduino-uno-pwm-output-and-servo-plugged-on-it-becomes-unstable-if-i-use-1wi/80701?noredirect=1#comment180410_80701
  [4]: https://arduino.stackexchange.com/questions/49421/arduino-reading-ds18b20-interferes-with-servo

title: Why does my delay get inaccurate after one minute ? It makes my servo vibrate

Answers: 1

body:
Without looking into the details of your code, it looks like you are
having issues with interrupts. According to your comment, this simple
code gives a very uneven pulse length:

```c++
digitalWrite(SERVO_PIN, HIGH);
delayMicroseconds(servo_value*1000);
digitalWrite(SERVO_PIN, LOW);
```

The function `delayMicroseconds()` delays for the requested time, _plus
any time taken by interrupts_. Thus, if the delay is inconsistent while
`servo_value` does not change, it can only be because of interrupts.
Trying to understand the exact symptoms is likely to be quite hard, as
one would have to dig into the source of the libraries you are using,
and look at every ISR in there. The fact that the version delaying with
`micros()` only starts misbehaving after some time is probably due to
some very slow “beating” between the timing of your servo and the timing
of an interrupt. The fact that the pulse is occasionally 20 µs
longer is consistent with it having been interrupted for 20 µs,
which for an ISR would be kind of long but not insanely long.

Rather than trying to analyze in detail how the interrupts are
interfering with your servo, I would recommend sidestepping the problem
completely and driving the servo with a hardware-generated PWM signal.
That would give a very consistent pulse length, completely immune to
being disrupted by interrupts. You can achieve 0.5 µs resolution
with a 20 ms period by setting Timer 1 to fast PWM and
clocking it at 2 MHz, like this:

```c++
// Configure timer 1 for driving a servo
// on pin OC1A = PB1 = digital 9.
void setup_timer()
{
    TCCR1A = 0;           // undo the Arduino core configuration
    TCCR1B = 0;           // ditto
    ICR1   = 40000 - 1;   // period = 20 ms = 40000 timer ticks
    OCR1A  =  3000 - 1;   // pulse length = 1.5 ms = 3000 timer ticks
    TCCR1A = _BV(COM1A1)  // non-inverting PWM on OC1A
           | _BV(WGM11);  // mode 14: fast PWM, TOP = ICR1
    TCCR1B = _BV(WGM12)   // ditto
           | _BV(WGM13)   // ditto
           | _BV(CS11);   // clock @ F_CPU/8 = 2 MHz
}
```

Then you can change the pulse length simply by writing to `OCR1A`: write
one less than the desired pulse length, in units of 0.5 µs.


body:
I'm attempting to use a SparkFun bidirectional level shifter  ([Link here][1]) to connect up a 3.3v wii nunchuk to a 5v Arduino Uno circuit. For now all I'm trying to do is write the position of the joystick and buttons into the monitor. When I include the shifter in the circuit, the code returns values that are way off what they should be, into the thousands or sometimes minuses. However, when I connect the controller without the shifter (at risk of burning out my controller), the code runs as normal, returning back the x and y axis of the joystick at around 130. Both push buttons have a similar issue, where they read as pressed at random intervals when not even touched. What could be causing the data to be off? I've tried rewiring several times, and am following the SparkFun general use page as a guide, and so hopefully miswiring shouldn't be the issue.

Here is the code:

    #include <Wire.h>
    #include <ArduinoNunchuk.h>

    #define BAUDRATE 19200

    ArduinoNunchuk nunchuk = ArduinoNunchuk();

    void setup()
    {
      Serial.begin(BAUDRATE);
      nunchuk.init();
    }

    void loop()
    {
      nunchuk.update();
      Serial.print(nunchuk.analogX, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.analogY, DEC);
      Serial.print(' ');
      Serial.print(nunchuk.zButton, DEC);
      Serial.print(' ');
      Serial.println(nunchuk.cButton, DEC);
      Serial.print(' ');
      delay(250);
    }

Library source :http://www.gabrielbianconi.com/projects/arduinonunchuk/

  [1]: https://www.sparkfun.com/products/12009?_ga=2.252391821.529997564.1650707299-678983415.1650707299

title: I2C and logic shifter troubleshooting

Answers: 0


body:
Im using <LiquidCrystal.h> arduino library,on a 2x16 LCD screen, with an accelerometer. I'd like to flip the the text when my x value exceeds N value. I get how to output text.
I tried straight up flipping the text, with an online converter, but the text that renders is garbage.
`  lcd.print("¡pןɹoʍ 'oןןǝɥ");  // Print a message to the LCD.`

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/Vne8c.png

title: Flip text in LCD screen

Answers: 1

body:
It's not possible. The text is a simple ASCII character set that is encoded in ROM. It can't (other than a few user-defined characters) be changed. And being simple ASCII it doesn't support any UNICODE characters which are used for "upside down" text.

To do what you want you'd need a graphical LCD screen instead of a pure text one.


body:
Im having trouble in sending float number and multiple float numbers.
Im currently working on project matlab and arduino mkr1000. The situation is that i want to send float number and multiple float numbers through communication(which in client.available() code) and view it in Serial Monitor. I have been searching throughout the internet but unfortunately could not receive it. The more i read the more confused i became. Im new to this environment. I do need consider bitshifting right?. Is there any similar examples and guidances from others would be really highly appreciated. Thank you.

Arduino Ide
```
    /* Latest Progress of the Project*/
#include <SPI.h>
#include <WiFi101.h>

// sensitive data placed in arduino_secrets.h
#include "arduino_secrets.h"
char ssid[] = SECRET_SSID; // name wifi
char pass[] = SECRET_PASS; // password
int status = WL_IDLE_STATUS; // status of wifi

// variables used
float value;

IPAddress ipserver(192, 168, 1, 109); // home wifi ip address

// initialize the client library
WiFiClient client;

void setup()
{
  // initialize serial and wait for port to open:
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  Serial.println("Attempting to connect to WPA network...");
  Serial.print("SSID:");
  Serial.println(ssid);

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED)
  {
    // will keep trying until connected
    Serial.print("Attempting to connect to network: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds(enough time) for connection:
    delay(10000);
  }

  // if you're connected now, so print the data status:
  Serial.println("You're connected to the network");
  Serial.println("------------------------------------");
  Serial.println("Hi FYP63333 Group");
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  Serial.println("------------------------------------");
  Serial.println("\nStarting connection to server...");
}

void loop()
{
  // Client connect or not connect in serial monitor:
  if (!client.connect(ipserver, 1234))
  {
    // if you didnt't get a connection to the server:
    Serial.println("Can't connect to server, try again.");
    delay(5000);
    return;
  }
  else
  {
    // if you get connection to the server:
    Serial.println("Connected to server!!!");
    Serial.println("MATLAB READY");
    //client.println("Hello from MKR1000");
  }

  // If there are incoming bytes available from the server, read and print them
  // Read all the lines of the reply from server and print them inside Serial Monitor:
  Serial.println();
  Serial.println("Incoming and receiving data from remote server:");
  while (client.connected() || client.available() || Serial.available())
  {
    while (Serial.available())
    {
      char data;
      data = Serial.read();
      if (client.connected())
      {
        client.print(data);
      }
    }
    while (client.available())
    {

      //------------------main-code(works)--------------for string//
      char ch = static_cast<char>(client.read());
      Serial.println(ch);
    }
  }

  // if the server's disconnected, stop the client:
  if (!client.connected())
  {
    Serial.println();
    Serial.println("Disconnecting from the server.");
    client.stop();
  }
}
```

Matlab code
```
clear;
clc;
%% Connecting matlab and Arduino IDE(TCP/IP Server)
t = tcpserver("192.168.1.109",1234);
t.ByteOrder = "big-endian";
```

title: Problem on Sending float number and multiple float numbers

Answers: 3

body:
Sending numerical values between systems is fraught with difficulty. Not only do you have to ensure that both ends agree on the size of the data (16 bit vs 32 bit ints, float vs double, etc) but that the byte ordering is handled correctly. On top of that is knowing *where* a number is in the stream of data. With nothing to delimit each value (and when you have 8 bits of communication width and 8 bits of data there's no room for "out of band" control signals) yo have no way of knowing which byte in the data stream corresponds to which byte in a value's raw data.

It's far better to encode the data into some other format that leaves you room to add delimiting control signals and has a predefined machine-agnostic data format.

The simplest encoding: ASCII. Simply "print" the numbers as text with the precision you desire (number of decimal places) as one number per line. Then on the Arduino you can read text data a line at a time then use the internal float conversion routines to turn that data into an actual floating point value again.

Some references:

* [Reading Serial on the Arduino](https://majenko.co.uk/blog/our-blog-1/reading-serial-on-the-arduino-27) - a blog post by me, also applicable to TCP/IP communication
* [String::toFloat()](https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tofloat/) - Converting a `String` object to a floating point value
* [strtof()](https://www.cplusplus.com/reference/cstdlib/strtof/) - Convert a C string to a floating point value

body:
Check out the I2C_Anything library.  It is used to transfer any data type bit-by-bit using the I2C serial protocol, but the algorithms could be just as easily used over ANY serial connection.  You do have to make sure that the size of a particular datatype is the same on both ends, but that's about it.

    Here's my subroutine running on a Teensy 3.5 that acquires VL53L0X LIDAR data from another Arduino processor (actually a Teensy 3.2).

        bool GetRequestedVL53l0xValues(VL53L0X_REQUEST which)
    {
      //Purpose: Obtain VL53L0X ToF sensor data from Teensy sensor handler
      //Inputs:
      // which = VL53L0X_REQUEST value denoting which combination of value to retrieve
      //  VL53L0X_CENTERS_ONLY -> Just the left/right center sensor values
      //  VL53L0X_RIGHT -> All three right sensor values, in front/center/rear order
      //  VL53L0X_LEFT -> All three left sensor values, in front/center/rear order
      //  VL53L0X_ALL -> All seven sensor values, in left/right front/center/rear/rear order
      //  VL53L0X_REAR_ONLY -> added 10/24/20 Just the rear sensor reading

      //Outputs:
      // Requested sensor values, obtained via I2C from the VL53L0X sensor handler
      // Returns TRUE if data retrieval successful, otherwise FALSE
      //Plan:
      // Step1: Send request to VL53L0X handler
      // Step2: get the requested data
      //Notes:
      // Copied from FourWD_WallE2_V4.ino's IsIRBeamAvail() and adapted
        // 08/05/20 added a VL53L0X_ALL request type
        // 01/24/21 added error detection/reporting
        // 01/16/22 rev to use I2C_Anything1 functions for Wire1

      //Step1: Send request to VL53L0X handler
      //DEBUG!!
        //myTeePrint.printf("Sending %d to slave\n", which);
      //DEBUG!!

      //myTeePrint.printf("In GetRequestedVL53l0xValues(%d)\n", (int)which);

      //03/01/22 rev to cvt all readings to cm
      uint16_t Lidar_RightFrontMM = 0;
      uint16_t Lidar_RightCenterMM = 0;
      uint16_t Lidar_RightRearMM = 0;
      uint16_t Lidar_RearMM = 0;

      uint16_t Lidar_LeftFrontMM = 0;
      uint16_t Lidar_LeftCenterMM = 0;
      uint16_t Lidar_LeftRearMM = 0;

      Wire1.beginTransmission(VL53L0X_I2C_SLAVE_ADDRESS);
      I2C_writeAnything((uint8_t)which, &Wire1);
      Wire1.endTransmission();

      //Step2: get the requested data
      int readResult = 0;
      int data_size = 0;
      switch (which)
      {
      case VL53L0X_READYCHECK: //11/10/20 added to prevent bad reads during Teensy setup()
        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, (uint16_t)(sizeof(bVL53L0X_TeensyReady)));
        readResult = I2C_readAnything(bVL53L0X_TeensyReady, &Wire1);
        break;

      case VL53L0X_CENTERS_ONLY:
        //just two data values needed here
        data_size = 2 * sizeof(uint16_t);
        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, (uint16_t)(2 * sizeof(Lidar_RightCenterMM)));
        readResult = I2C_readAnything(Lidar_RightCenterMM, &Wire1);
        glRightCenterCm = Lidar_RightCenterMM / 10; //integer truncation OK

        if (readResult > 0)
        {
          I2C_readAnything(Lidar_LeftCenterMM, &Wire1);
          glLeftCenterCm = Lidar_LeftCenterMM / 10; //integer truncation OK
        }

        //DEBUG!!
            //myTeePrint.printf("VL53L0X_CENTERS_ONLY case: Got LC/RC = %d, %d\n", Lidar_LeftCenterMM, Lidar_RightCenterMM);
        //DEBUG!!

        break;
      case VL53L0X_RIGHT:
        //four data values needed here
        data_size = 3 * sizeof(uint16_t) + sizeof(float);

        //DEBUG!!
            //myTeePrint.printf("data_size = %d\n", data_size);
        //DEBUG!!

        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, data_size);
        readResult = I2C_readAnything(Lidar_RightFrontMM, &Wire1);
        glRightFrontCm = Lidar_RightFrontMM / 10; //integer truncation OK

        if (readResult > 0)
        {
          readResult = I2C_readAnything(Lidar_RightCenterMM, &Wire1);
          glRightCenterCm = Lidar_RightCenterMM / 10; //integer truncation OK
        }
        if (readResult > 0)
        {
          readResult = I2C_readAnything(Lidar_RightRearMM, &Wire1);
          glRightRearCm = Lidar_RightRearMM / 10; //integer truncation OK
        }
        if (readResult > 0)
        {
          readResult = I2C_readAnything(glRightSteeringVal, &Wire1);
        }

        //DEBUG!!
            //myTeePrint.printf("VL53L0X_RIGHT case: Got L/C/R/S = %d, %d, %d, %3.2f\n",
            // glRightFrontCm, Lidar_RightCenterMM, Lidar_RightRearMM, ToFSteeringVal);
        //DEBUG!!

        break;
      case VL53L0X_LEFT:
        //four data values needed here
        //data_size = 3 * sizeof(int) + sizeof(float);
        data_size = 3 * sizeof(uint16_t) + sizeof(float);

        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, data_size);
        readResult = I2C_readAnything(Lidar_LeftFrontMM, &Wire1);
        glLeftFrontCm = Lidar_LeftFrontMM / 10; //integer truncation OK

        if (readResult > 0)
        {
          readResult = I2C_readAnything(Lidar_LeftCenterMM, &Wire1);
          glLeftCenterCm = Lidar_LeftCenterMM / 10; //integer truncation OK
        }
        if (readResult > 0)
        {
          readResult = I2C_readAnything(Lidar_LeftRearMM, &Wire1);
          glLeftRearCm = Lidar_LeftRearMM / 10; //integer truncation OK
        }
        if (readResult > 0)
        {
          readResult = I2C_readAnything(glLeftSteeringVal, &Wire1);
        }

        //DEBUG!!
            //myTeePrint.printf("VL53L0X_RIGHT case: Got L/C/R/S = %d, %d, %d, %3.2f\n",
            // Lidar_LeftFrontMM, Lidar_LeftCenterMM, Lidar_LeftRearMM, ToFSteeringVal);
        //DEBUG!!

        break;
      case VL53L0X_ALL: //added 08/05/20, chg to VL53L0X_ALL 10/31/20
        //nine data values needed here - 7 ints and 2 floats
        data_size = 7 * sizeof(uint16_t) + 2 * sizeof(float); //10/31/20 added rear distance

        //myTeePrint.printf("In VL53L0X_ALL case with data_size = %d\n", data_size);

        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, data_size);

        //Lidar_LeftFrontMM
        readResult = I2C_readAnything(Lidar_LeftFrontMM, &Wire1);
        glLeftFrontCm = Lidar_LeftFrontMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_LeftFrontMM))
        {
          myTeePrint.printf("Error reading Lidar_LeftFrontMM\n");
        }

        //Lidar_LeftCenterMM
        readResult = I2C_readAnything(Lidar_LeftCenterMM, &Wire1);
        glLeftCenterCm = Lidar_LeftCenterMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_LeftCenterMM))
        {
          myTeePrint.printf("Error reading Lidar_LeftCenterMM\n");
        }

        //Lidar_LeftRearMM
        readResult = I2C_readAnything(Lidar_LeftRearMM, &Wire1);
        glLeftRearCm = Lidar_LeftRearMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_LeftRearMM))
        {
          myTeePrint.printf("Error reading Lidar_LeftRearMM\n");
        }

        //glLeftSteeringVal
        readResult = I2C_readAnything(glLeftSteeringVal, &Wire1);
        if (readResult != sizeof(glLeftSteeringVal))
        {
          myTeePrint.printf("Error reading glLeftSteeringVal\n");
        }

        //Lidar_RightFrontMM
        readResult = I2C_readAnything(Lidar_RightFrontMM, &Wire1);
        glRightFrontCm = Lidar_RightFrontMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_RightFrontMM))
        {
          myTeePrint.printf("Error reading Lidar_RightFrontMM\n");
        }

        //Lidar_RightCenterMM
        readResult = I2C_readAnything(Lidar_RightCenterMM, &Wire1);
        glRightCenterCm = Lidar_RightCenterMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_RightCenterMM))
        {
          myTeePrint.printf("Error reading Lidar_RightCenterMM\n");
        }

        //Lidar_RightRearMM
        readResult = I2C_readAnything(Lidar_RightRearMM, &Wire1);
        glRightRearCm = Lidar_RightRearMM / 10; //integer truncation OK

        if (readResult != sizeof(Lidar_RightRearMM))
        {
          myTeePrint.printf("Error reading Lidar_RightRearMM\n");
        }

        //Lidar_RearMM
        readResult = I2C_readAnything(Lidar_RearMM, &Wire1);
        glRearCm = Lidar_RearMM / 10; //integer truncation OK
        if (readResult != sizeof(Lidar_RearMM))
        {
          myTeePrint.printf("Error reading Lidar_RearMM\n");
        }

        //glRightSteeringVal
        readResult = I2C_readAnything(glRightSteeringVal, &Wire1);
        if (readResult != sizeof(glRightSteeringVal))
        {
          myTeePrint.printf("Error reading glLeftSteeringVal\n");
        }

        //myTeePrint.printf("%lu: VL53l0x - %d, %d, %d, %d, %d, %d, %d\n",
        // millis(),
        // Lidar_LeftFrontMM, Lidar_LeftCenterMM, Lidar_LeftRearMM,
        // glRightFrontCm, Lidar_RightCenterMM, Lidar_RightRearMM,
        // Lidar_RearMM);
        break; //10/31/20 bugfix

      case VL53L0X_REAR_ONLY:
        //just ONE data value needed here
        data_size = sizeof(uint16_t);
        Wire1.requestFrom(VL53L0X_I2C_SLAVE_ADDRESS, (uint16_t)(sizeof(Lidar_RearMM)));
        readResult = I2C_readAnything(Lidar_RearMM, &Wire1);
        glRearCm = Lidar_RearMM / 10; //integer truncation OK

        //DEBUG!!
            //myTeePrint.printf("VL53L0X_REAR_ONLY case: Got Rear = %d\n", Lidar_RearMM);
        //DEBUG!!

        break;

      default:
        break;
      }
      //myTeePrint.printf("GetRequestedVL53l0xValues(): LR/LC/LF/RR/RC/RF/R = %d\t%d\t%d\t%d\t%d\t%d\t%d\n",
      //  Lidar_LeftRearMM, Lidar_LeftCenterMM, Lidar_LeftFrontMM,
      //  Lidar_RightRearMM, Lidar_RightCenterMM, glRightFrontCm, Lidar_RearMM);

      return readResult > 0; //this is true only if all reads succeed
    }

and here's the corresponding code on the other end of the I2C link:

    // function that executes whenever data is requested by master
    // this function is registered as an event, see setup()
    void requestEvent()
    {
      //Purpose: Send requested sensor data to the Mega controller via main I2C bus
      //Inputs:
      //  request_type = uint8_t value denoting type of data requested (from receiveEvent())
      //      0 = left & right center distances only
      //      1 = right side front, center and rear distances, plus steering value
      //      2 = left side front, center and rear distances, plus steering value
      //      3 = both side front, center and rear distances, plus both steering values
    //Outputs:
      //  Requested data sent to master
      //Notes:
      //  08/05/20 added VL53L0X_ALL request type to get both sides at once
      //  10/24/20 added VL53L0X_REAR_ONLY request type
      //  11/09/20 added write to pin for O'scope monitoring

      int data_size = 0;

    //DEBUG!!
        //Serial.printf("RequestEvent() with request_type = %d: VL53L0X Front/Center/Rear distances = %d, %d, %d\n",
        //    request_type, RF_Dist_mm, RC_Dist_mm, RR_Dist_mm);
    //DEBUG!!

      //digitalWrite(LED_BUILTIN, HIGH);//added 01/22/22
      digitalWrite(REQUEST_EVENT_DURATION_OUTPUT_PIN, HIGH);

      digitalToggle(LED_BUILTIN);//2/21/22 added for visual indication of I2C activity
      switch (request_type)
      {
      case  VL53L0X_READYCHECK: //added 11/10/20 to prevent bad reads during Teensy setup()
        //Serial.printf("in VL53L0X_READYCHECK case at %lu with bTeensyReady = %d\n", millis(), bTeensyReady);
        I2C_writeAnything(bTeensyReady);
        break;

      case VL53L0X_CENTERS_ONLY:

        //DEBUG!!
          //data_size = 2*sizeof(uint16_t);
          //Serial.printf("Sending %d bytes LC_Dist_mm = %d, RC_Dist_mm = %d to master\n", data_size, LC_Dist_mm, RC_Dist_mm);
        //DEBUG!!

        I2C_writeAnything(RC_Dist_mm);
        I2C_writeAnything(LC_Dist_mm);
        break;

      case VL53L0X_RIGHT:

        //DEBUG!!
                //data_size = 3 * sizeof(uint16_t) + sizeof(float);
                //Serial.printf("Sending %d bytes RF/RC/RR/RS vals = %d, %d, %d, %3.2f to master\n",
                //    data_size, RF_Dist_mm, RC_Dist_mm, RR_Dist_mm, RightSteeringVal);
        //DEBUG!!

        I2C_writeAnything(RF_Dist_mm);
        I2C_writeAnything(RC_Dist_mm);
        I2C_writeAnything(RR_Dist_mm);
        I2C_writeAnything(RightSteeringVal);
        break;

      case VL53L0X_LEFT:

        //DEBUG!!
                //data_size = 3 * sizeof(uint16_t) + sizeof(float);
                //Serial.printf("Sending %d bytes LF/LC/LR/LS vals = %d, %d, %d, %3.2f to master\n",
                //    data_size, LF_Dist_mm, LC_Dist_mm, LR_Dist_mm, LeftSteeringVal);
        //DEBUG!!

        I2C_writeAnything(LF_Dist_mm);
        I2C_writeAnything(LC_Dist_mm);
        I2C_writeAnything(LR_Dist_mm);
        I2C_writeAnything(LeftSteeringVal);
        break;

      case VL53L0X_ALL:
        //Serial.printf("In VL53L0X_ALL case\n");
        //added 08/05/20 to get data from both sides at once
        //10/31/20 chg to VL53L0X_ALL & report all 7 sensor values

    //DEBUG!!
        //data_size = 3 * sizeof(uint16_t) + sizeof(float);
        //data_size = 7 * sizeof(uint16_t) + 2 * sizeof(float);
        //Serial.printf("Sending %d bytes to master\n", data_size);
        //Serial.printf("%d bytes: %d\t%d\t%d\t%3.2f\t%d\t%d\t%d\t%d\t%3.2f\n",
        //    data_size, LF_Dist_mm, LC_Dist_mm, LR_Dist_mm, LeftSteeringVal,
        //  RF_Dist_mm, RC_Dist_mm, RR_Dist_mm, Rear_Dist_mm, RightSteeringVal);
    //DEBUG!!

        //DEBUG!!
          //data_size = 3 * sizeof(uint16_t) + sizeof(float);
          //Serial.printf("Sending %d bytes LF/LC/LR/LS vals = %d, %d, %d, %3.2f to master\n",
          //    data_size, LF_Dist_mm, LC_Dist_mm, LR_Dist_mm, LeftSteeringVal);
        //DEBUG!!

        //left side
        I2C_writeAnything(LF_Dist_mm);
        I2C_writeAnything(LC_Dist_mm);
        I2C_writeAnything(LR_Dist_mm);
        I2C_writeAnything(LeftSteeringVal);

        //DEBUG!!
          //data_size = 3 * sizeof(uint16_t) + sizeof(float);
          //data_size = 4 * sizeof(uint16_t) + sizeof(float);
          //Serial.printf("Sending %d bytes RF/RC/RR/R/RS vals = %d, %d, %d, %d, %3.2f to master\n",
          //    data_size, RF_Dist_mm, RC_Dist_mm, RR_Dist_mm, Rear_Dist_mm, RightSteeringVal);
        //DEBUG!!

           //right side
        I2C_writeAnything(RF_Dist_mm);
        I2C_writeAnything(RC_Dist_mm);
        I2C_writeAnything(RR_Dist_mm);
        I2C_writeAnything(Rear_Dist_mm);
        I2C_writeAnything(RightSteeringVal);

        break;

      case VL53L0X_REAR_ONLY:

        //DEBUG!!
          //data_size = sizeof(uint16_t);
          //Serial.printf("Sending %d bytes Rear_Dist_mm = %d to master\n", data_size, Rear_Dist_mm);
        //DEBUG!!

        I2C_writeAnything(Rear_Dist_mm);
        break;

      default:
        break;
      }
      digitalToggle(LED_BUILTIN);//2/21/22 added for visual indication of I2C activity

      digitalWrite(REQUEST_EVENT_DURATION_OUTPUT_PIN, LOW);
      //digitalWrite(LED_BUILTIN, LOW);//added 01/22/22
    }

body:
As an alternative, you can send the numbers as text, as suggested by Edgar Bonet above.  Here's a short program I just whipped up that demos this capability, using two Teensy 3.x processors.  The program waits for a character on its serial port, and if any are found, they are transmitted to the other processor via a serial connection between the two, and also echoed back to the sending serial port.  This should work with any Arduino processor that has two serial ports (Serial for talking to the PC, Serial1 for talking to the other processor).  I used the built-in LED as an activity monitor.

    /*
        Name:       Serial_Anything.ino
        Created: 4/26/2022 6:23:01 PM
        Author:     FRANKNEWXPS15\Frank

        Project to demonstrate passing arbitrary data types over a serial connection
        The idea is to port I2C_Anything to use over a common serial port connection
    */

    #include "Serial_Anything.h"

    //char buff[30];

    void setup()
    {
      Serial.begin(115200);
      delay(1000);
      Serial1.begin(115200);
      delay(1000);

      Serial.printf("Serial_Anything Demo\n");

      pinMode(LED_BUILTIN, OUTPUT);

      digitalWrite(LED_BUILTIN, HIGH);
      delay(500);
      digitalWrite(LED_BUILTIN, LOW);
      delay(500);
      digitalWrite(LED_BUILTIN, HIGH);
      delay(500);
      digitalWrite(LED_BUILTIN, LOW);
      delay(500);

    }

    void loop()
    {
      if (Serial.available())
      {
        //buff[buffidx] = Serial.read();
        //buffidx++;
        char c = Serial.read();
        Serial1.write(c);
        digitalWrite(LED_BUILTIN, HIGH);
        delay(50);
        digitalWrite(LED_BUILTIN, LOW);
        Serial.write(c);
      }

      if (Serial1.available())
      {
        //buff[buffidx] = Serial.read();
        //buffidx++;
        char c = Serial1.read();
        Serial.write(c);
        digitalWrite(LED_BUILTIN, HIGH);
        delay(50);
        digitalWrite(LED_BUILTIN, LOW);
      }
    }

Here's a short section of output from a typical run:

Teensy1:

    Port closed
    Opening port
    Port open
    Serial_Anything Demo
    y
    y
    y
    y
    X
    X
    X
    X
    the quick
    314159
    3.14159

Teensy2:

    Opening port
    Port open
    y
    y
    y
    y
    y
    y
    y
    y
    y
    y
    y
    y
    y
    X
    X
    X
    X
    the quick
    314159
    3.14159


body:
I have a teensy4.1, with a 16 by 2 LCD screen, and an I2C LCD interface.
I was trying to write a bunch of custom characters to an LCD screen, to flip some text.

my issue is that it works fine, but on only up to 8 custom characters. any more than that produces odd results. with a loop of 16, the first 8 characters are printed. should more than 8 characters be defined, only the last assigned are in use.

I commented out all but the first 8 custom characters, and iterates through them in a loop of 16 iterations. this loops over the start. -- I guess that works as I would expect. If I define more than 8 custom Characters, only the last 8 assigned will output.

 Here is a picture of that in action:
[![customChar limits to 8][1]][1]

here is my code:

    #include <Adafruit_LiquidCrystal.h>
    Adafruit_LiquidCrystal lcd(0);

    //upside down char glyphs... default characters are 7x5 1 px w/space on the bottom
    //these glyphs are 7x5 with space on the top
    byte uA[8] = {  B00000,  B10001,  B10001,  B10001,  B11111,  B10001,  B10001,  B01110};
    byte uB[8] = {  B00000,  B01111,  B10001,  B10001,  B01111,  B10001,  B10001,  B01111};
    byte uC[8] = {  B00000,  B01110,  B10001,  B00001,  B00001,  B00001,  B10001,  B01110};
    byte uD[8] = {  B00000,  B00111,  B01001,  B10001,  B10001,  B10001,  B01001,  B00111};
    byte uE[8] = {  B00000,  B11111,  B00001,  B00001,  B01111,  B00001,  B00001,  B11111};
    byte uF[8] = {  B00000,  B00001,  B00001,  B00001,  B01111,  B00001,  B00001,  B11111};
    byte uG[8] = {  B00000,  B11110,  B10001,  B10001,  B11101,  B00001,  B10001,  B01110};
    byte uH[8] = {  B00000,  B10001,  B10001,  B10001,  B11111,  B10001,  B10001,  B10001};
    byte uI[8] = {  B00000,  B01110,  B00100,  B00100,  B00100,  B00100,  B00100,  B01110};
    byte uJ[8] = {  B00000,  B00110,  B01001,  B01000,  B01000,  B01000,  B01000,  B11100};
    byte uK[8] = {  B00000,  B10001,  B01001,  B00101,  B00011,  B00101,  B01001,  B10001};
    byte uL[8] = {  B00000,  B01111,  B00001,  B00001,  B00001,  B00001,  B00001,  B00001};
    byte uM[8] = {  B00000,  B10001,  B10001,  B10001,  B10101,  B10101,  B11011,  B10001};
    byte uN[8] = {  B00000,  B10001,  B10001,  B11001,  B10101,  B10011,  B10001,  B10001};
    byte uO[8] = {  B00000,  B01110,  B10001,  B10001,  B10001,  B10001,  B10001,  B01110};
    byte uP[8] = {  B00000,  B00001,  B00001,  B00001,  B01111,  B10001,  B10001,  B01111};
    byte uQ[8] = {  B00000,  B10110,  B01001,  B10101,  B10001,  B10001,  B10001,  B01110};
    byte uR[8] = {  B00000,  B10001,  B01001,  B00101,  B01111,  B10001,  B10001,  B01111};
    byte uS[8] = {  B00000,  B01111,  B10000,  B10000,  B01110,  B00001,  B00001,  B11110};
    byte uT[8] = {  B00000,  B00100,  B00100,  B00100,  B00100,  B00100,  B00100,  B11111};
    byte uU[8] = {  B00000,  B01110,  B10001,  B10001,  B10001,  B10001,  B10001,  B10001};
    byte uV[8] = {  B00000,  B00100,  B01010,  B10001,  B10001,  B10001,  B10001,  B10001};
    byte uW[8] = {  B00000,  B01010,  B10101,  B10101,  B10101,  B10001,  B10001,  B10001};
    byte uX[8] = {  B00000,  B10001,  B10001,  B01010,  B00100,  B01010,  B10001,  B10001};
    byte uY[8] = {  B00000,  B00100,  B00100,  B00100,  B01010,  B10001,  B10001,  B10001};
    byte uZ[8] = {  B00000,  B11111,  B00001,  B00010,  B00100,  B01000,  B10000,  B11111};
    //pockets
    byte cornerA[]={B11111,B10000,B10000,B10000,B10000,B10000,B10000,B10000};//top left
    byte cornerB[]={B10000,B10000,B10000,B10000,B10000,B10000,B10000,B11111};//btm left
    byte cornerC[]={B11111,B00001,B00001,B00001,B00001,B00001,B00001,B00001};//top right
    byte cornerD[]={B00001,B00001,B00001,B00001,B00001,B00001,B00001,B11111};//btm right
    void flip(char *text);
    void setup() {
      Serial.begin(9600);
      lcd.begin(16,2); //
      //flipped characters
    lcd.createChar(0,uA);
    lcd.createChar(1,uB);
    lcd.createChar(2,uC);
    lcd.createChar(3,uD);
    lcd.createChar(4,uE);
    lcd.createChar(5,uF);
    lcd.createChar(6,uG);
    lcd.createChar(7,uH);
    lcd.createChar(8,uI);
    lcd.createChar(9,uJ);
    lcd.createChar(10,uK);
    lcd.createChar(11,uL);
    lcd.createChar(12,uM);
    lcd.createChar(13,uN);
    lcd.createChar(14,uO);
    lcd.createChar(15,uP);
    /*lcd.createChar(16,uQ);
    lcd.createChar(17,uR);
    lcd.createChar(18,uS);
    lcd.createChar(19,uT);
    lcd.createChar(20,uU);
    lcd.createChar(21,uV);
    lcd.createChar(22,uW);
    lcd.createChar(23,uX);
    lcd.createChar(24,uY);
    lcd.createChar(25,uZ);
    lcd.createChar(26,cornerA);
    lcd.createChar(27,cornerB);
    lcd.createChar(28,cornerC);
    lcd.createChar(29,cornerD);
    */
      //ascii coversion prolly like n+66
      //setCursor be like: (column, row) 16 cols, 2 rows, both start at 0
    lcd.setCursor(0,0);

      for (int i=0; i<16;i++){
      lcd.write(i); //prints ABCDEFGHABCDEFGH
      lcd.setCursor(i+1,0);
      delay (500);
      }
      lcd.setCursor(0,1);
      lcd.print("LIMIT 8 CHARS?");
    }

    void loop() {}

I would like to make more than 8 customChars, am I approaching this correctly? is there a limit somewhere I can change?

  [1]: https://i.stack.imgur.com/jWmrN.jpg

title: lcd.createChar() only allows for 8 custom characters

Answers: 1

body:
These displays only allow up to 8 custom defined characters. The hardware just only has the character RAM for at most 8 characters. They will be mapped to char codes 0 to 7 and 8 to 15. The character code 8 always prints the same character as code 0, 9 as 1 and so on.

So no, there is no way to use more than 8 custom characters _at once_. Of course, you can change the characters dynamically, so that a certain location of the screen always shows a changing custom character icon.


body:
I am making a hydroponic nutrient monitoring system using Arduino Uno, Atlas  Scientific EC sensor, pH sensor, and RTD (temperature) sensor in I2C mode. I also want to use LCD 20x04 to display the sensor reading so that will display the EC, pH, and temperature values.
I connect all the SDA and SCL to pin A4 (SDA) and A5 (SCL), and powered all the sensors and LCD with 3.3 V. Each sensor's SDA and SCL are added with resistor 4.7 kOhm.

[![The Fritzing of my circuit][1]][1]

I tested the code first by connecting my Arduino Uno to the RTD EZO circuit and sensors, without the LCD. The Serial Monitor successfully displays the data sensor reading of RTD, as well as 'No Data' for EC and pH as I do not connect the EC and pH sensors. But when I connect all the circuits and sensors, it can not detect the pH sensor. The most frustrating part is the LCD. The LCD at first displays the EC and RTD data, but only run for 5 minutes and freeze. The LCD sometimes only shows a "0.00" value for EC and RTD even though the Serial Monitor shows the data sensor reading.

I want to know if there is something wrong with my code or maybe the problem with my own circuit.

Here is the code:

    #include <Ezo_i2c.h>
    #include <Wire.h>                //enable I2C.
    #include <LiquidCrystal_I2C.h>

    Ezo_board ec = Ezo_board(100, "EC");
    Ezo_board ph = Ezo_board(99, "PH");
    Ezo_board temp = Ezo_board(102, "RTD");
    LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);

    bool reading_request_phase = true;        //selects our phase

    uint32_t next_poll_time = 0;              //holds the next time we receive a response, in milliseconds
    const unsigned int response_delay = 1000; //how long we wait to receive a response, in milliseconds

    void setup()                     //hardware initialization.
    {
      Serial.begin(9600);            //enable serial port.
      Wire.begin();                  //enable I2C port.
      Serial.println("ATLAS EZO I2C v2");
      Serial.print("Test date: ");
      lcd.init();
      lcd.backlight();
      lcd.setCursor(1,1);
      lcd.print("ATLAS EZO I2C v2");
      lcd.setCursor(0,2);

      delay(3000);
      lcd.clear();
     }

      void loop() {                                                      //the main loop.
      lcd.setCursor(0,1);
      lcd.print("EC: ");
      lcd.setCursor(4,1);
      lcd.print(ec.get_last_received_reading());
      lcd.setCursor(10,1);
      lcd.print("ppm");
      lcd.setCursor(0,2);
      lcd.print("pH: ");
      lcd.setCursor(4,2);
      lcd.print(ph.get_last_received_reading());
      lcd.setCursor(0,3);
      lcd.print("Temp.: ");
      lcd.setCursor(7,3);
      lcd.print(temp.get_last_received_reading());
      lcd.setCursor(13,3);
      lcd.print("C");

      if (reading_request_phase)             //if were in the phase where we ask for a reading
      {
        //send a read command
        //to let the library know to parse the reading
        ec.send_read_cmd();
        ph.send_read_cmd();
        temp.send_read_cmd();

        next_poll_time = millis() + response_delay;         //set when the response will arrive
        reading_request_phase = false;                      //switch to the receiving phase
      }
      else                                                //if were in the receiving phase
      {
        if (millis() >= next_poll_time)                    //and its time to get the response
      {
        receive_reading(ec);                              //get the reading from the EC circuit
        receive_reading(ph);                              //get the reading from the PH circuit
        receive_reading(temp);                              //get the reading from the RTD circuit

        reading_request_phase = true;                     //switch back to asking for readings
      }
     }
     }

      void receive_reading(Ezo_board &Sensor) {
      Serial.println();
      Serial.print(Sensor.get_name()); //print the name of the EZO circuit
      Serial.print(": ");
      Sensor.receive_read_cmd();

      switch (Sensor.get_error())                          //switch case based on what the response code is.
         {
        case Ezo_board::SUCCESS:
        Serial.print(Sensor.get_last_received_reading());               //the command was successful, print the reading
        break;

        case Ezo_board::FAIL:
        Serial.print("Failed ");                          //means the command has failed.
        break;

        case Ezo_board::NOT_READY:
        Serial.print("Pending ");                         //the command has not yet been finished calculating.
        break;

        case Ezo_board::NO_DATA:
        Serial.print("No Data ");                         //the sensor has no data to send.
        break;
     }
    }

  [1]: https://i.stack.imgur.com/t4PbL.jpg

title: I2C sensors not working when I connect to LCD 20X04

Answers: 2

body:
Welcome to Stack Exchange!

I can spot a few problems with the circuit. As @hcheung said, the I2C pull-up resistors should only be wired between SDA>3.3V and SCL>3.3V (in parallel), not in series with the sensors.

Also, another warning: You are powering your sensors with **3.3V**, but the outputs from the Arduino Uno are **5V!** Many boards will not like this and might fry themselves, or at least not function correctly. Their signals will also be 3.3V instead of 5V, potentially causing more weird behavior.

If all your components are compatible with 5 volt power (check their datasheets/guides), I would recommend powering them all with 5 volts.

Otherwise, you will need level shifters to convert between the 5V Arduino signals and the 3.3V board signals.

body:
Thank you for all your help.
I now realize that I have made the wrong I2C circuits. Then I modified them and now the program and the sensors work perfectly.

Here is my circuit now.

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/BHgWA.jpg


body:
I have an Arduino Due and a 2.4" TFT screen shield [this one](http://www.lcdwiki.com/2.4inch_Arduino_Display#Program_Download).  I'm trying to turn off the backlight to save power but not having any luck.  I'm using the super nice MCUFriend library:

    #include <Adafruit_GFX.h>
    #include <MCUFRIEND_kbv.h>
    MCUFRIEND_kbv tft;

It has worked great to make buttons and graphics, it's just the backlight I can't figure out.  There's a [datasheet](http://www.lcdwiki.com/res/MAR2406/ILI9341_Datasheet.pdf) for the driver chip and it has the following section to `Write CTRL Display`, which is what I imagine I need:
[![enter image description here][1]][1]

So I have been trying to send 0x00 to register 0x53, but the display stays lit.  I've tried using MCUFriend_kbv to set it, then thought maybe I'm doing something wrong so I tried their sample `LCD_ID_readreg.ino` and added some lines:

    readReg(0x54, 3, "Read CTRL Display");
    lcdWriteRegister(0x53, 0x00);
    readReg(0x54, 3, "Read CTRL Display after update");

I am not sure if I'm just misunderstanding something but the results show:

    reg(0x0054) 00 00 00 Read CTRL Display
    reg(0x0054) 00 00 00 Read CTRL Display after update

I guess I was expecting the register to say the backlight was on before I update it, but it says `00` even before I make the update- yet the backlight is clearly on.  Any idea what I'm missing?  Maybe it's the comment there about "control lines must be low"?  I have no idea what that means.  If you search the document for "control lines" nothing comes up.

The read above to 0x54 is because that's apparently where you read that register (unlike some where you call the same address to read/write):
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/2VRCq.png
  [2]: https://i.stack.imgur.com/AH6Uw.png

title: Turn off backlight on 2.4" TFT screen

Answers: 1

body:
That screen has no backlight control. The same chip is used on many LCDs and whether the inbuilt backlight control registers are used very much depends on the screen the chip is attached to.

If you want to control the backlight you will have to modify the shield to allow access to the right signal. I can't get a schematic for that specific screen, but from the images it looks like R2 on the underside may be a current limiting resistor for the backlight. Removing that resistor may turn off the back light, in which case you could replace it with a suitable transistor and similar resistor (you will have to check if it's high-side or low-side switched - does it provide power to the LEDs or sink it to ground) which you can control from a free GPIO pin.


body:
I have setup two ESP32-CAMs, sharing the signal from a PIR sensor via an optocoupler.

Plus I have a 12V LED ring on a 5V to 12V booster, turned on/off by a relay.

The ESP32s go to deep sleep, wake up on the signal from the PIR sensor, turn on the 12V IR LED ring, take some photos and go back to deep sleep.

When they are on three separate power circuits, they seem to work well.

Is it safe to connect all these to the same USB output from an USB power bank?

Or can it be done safely at all?

(Could be similar to [this question][1] but I'm not sure.)

I am new at this and I don't have any intuition about whether that would create odd voltages and currents that might damage the components on the long-term, as they keep turning on/off and draw varying amount of power.

Instead of three USB connections like this:

(trying to illustrate only the power circuits)

[![three usbs][2]][2]

I would like to power them on one USB connection:

[![one usb][3]][3]

  [1]: https://arduino.stackexchange.com/questions/28930/is-it-safe-to-use-the-same-power-source-for-arduino-and-its-motor-shield
  [2]: https://i.stack.imgur.com/Ezo0c.png
  [3]: https://i.stack.imgur.com/eBkM0.png

title: Is it safe to power multiple ESP32-CAM circuits from the same battery output?

Answers: 1

body: There is no difference between your circuits. Internally to the powerbank all three outlets are typically wired together just like in your second schematic. One outlet or three outlets it's all the same.


body: I'm new to Arduino. I'm curious whether there is a standard way to record the plan of a device—for instance, if I wanted to share it or communicate the design to other people. I realize the short answer here might be, “yes, make a circuit diagram.” Are there perhaps widely used tools for producing those, perhaps with add-ons for Arduino boards? (I'd prefer a more semantic representation than, say, making a diagram in Inkscape.)

title: Is there a standard way to describe devices?

Answers: 1

body:
There is no plugin to a program like Inkscape - as far as I know. It doesn't make much sense to have one. With an Arduino circuit you normally want to show the real electrical connections. A block diagram without real electrical connections doesn't help much in reproducing the project. You can do it, but you will have to do it on your in in a graphic program. I think this is only helpful for rather big projects, where each block contains not only the Arduino but also many further components of that functional unit in your project.

To show the circuit you basically have 2 options:

- **A wiring diagram:** This is an image, mostly created via the software [Fritzing][1], which shows a breadboard and the components of the project placed on it. The electrical connections are represented by colored lines. This is good for beginners, who cannot yet read a schematic and want to reproduce the circuit on their own breadboard. Though wiring diagrams, especially Fritzing, is only standard in the Arduino/Beginner world. The more you get into professional realm, the less you will see them. They look like this (please note the internal connections, that a breadboard has in its numbered rows):

    [![enter image description here][2]][2]

- **A schematic:** A schematic is the standard way of describing any electronic circuit. For example look at the [Arduino Uno schematic][3]. Every part is represented by a symbol with pins. The pins get connected with lines (representing wires or PCB traces). There are many different softwares for creating schematics, for example Eagle, KiCAD, EasyEDA and Altium Designer. You can choose yourself what to use. Look at the options, that the softwares provide. Some are premium but have free options, others (like KiCAD) are open source. I personally use KiCAD. At least for KiCAD you can download part repository files (like [this one][4]), which include Arduino boards, so that you can place them directly on your schematic. I'm sure there are similar resources for other programs as well. Export the resulting schematic to PDF or an image format so that everyone can read the schematic without having your program installed.

   An additional benefit in creating a schematic is, that all these programs also support creating a PCB layout from the schematic. So it gets easier to design a PCB from your circuit for DIY or ordered production.

  [1]: https://fritzing.org/
  [2]: https://i.stack.imgur.com/SDVyV.png
  [3]: https://www.arduino.cc/en/uploads/Main/arduino-uno-smd-schematic.pdf
  [4]: https://www.opensourceagenda.com/projects/arduino-kicad-library


body:
I am trying to get a web server to run on the ESP12E on the Node MCU variant, and following the example from the esp8266 documentation page [here](https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/server-examples.html). But the code does not compile, throwing the following error message:

```
'class WiFiServer' has no member named 'accept'; did you mean '_accept'?
```

I'm relatively new to MCUs in general, and cannot find a solution for this on any website. Any help would be appreciated.

title: Node MCU Esp12-E does not support server accept function

Answers: 1

body:
The 'latest' documentation applies for git master branch.

`accept()` is ready for the next release of Arduino esp8266. It will be version 3.1.0. Until then you can use `server.available()`. It works the same way as `accept()` in ESP8266WiFi library's WiFiServer.

I initiated the addition of `server.accept()`, because `server.available()` in esp8266 WiFiServer works as Ethernet library's `server.accept()`, not as `server.available()`.


body:
I'm using a simple electrode microphone with an Arduino UNO board with the aim of detecting peak frequencies in the output signal overtime. I set the sampling rate to 1 MHz, but i can't pick up a peak that is above 4000 Hz(I've verified the values with regression but it's only true for the range [200 Hz, 3900 Hz]). So my questions are:
- Is this due to the microphone's sensibility or to the Arduino UNO?
- Someone suggested me an ESP32, but i don't understand what difference it'll make.

CODE:

    #include "arduinoFFT.h"
    float peak = 0;
    float val = 0;
    #define SAMPLES 128            //SAMPLES-pt FFT. Must be a base 2 number. Max 128 for Arduino Uno.
    #define SAMPLING_FREQUENCY 1000000 //Ts = Based on Nyquist, must be 2 times the highest expected frequency.

    arduinoFFT FFT = arduinoFFT();

    unsigned int samplingPeriod;
    unsigned long microSeconds;

    double vReal[SAMPLES]; //create vector of size SAMPLES to hold real values
    double vImag[SAMPLES]; //create vector of size SAMPLES to hold imaginary values

    void setup()
    {
        Serial.begin(115200);
        samplingPeriod = round(1000000*(1.0/SAMPLING_FREQUENCY)); //Period in microseconds

    }

    void loop()
    {

        for(int i=0; i<SAMPLES; i++)
        {
            microSeconds = micros();
            val = analogRead(0);
            vReal[i] = val;
            vImag[i] = 0;

            while(micros() < (microSeconds + samplingPeriod))
            {

            }
        }

        FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
        FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
        FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

        peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
        Serial.println((peak-5063)/122.5);
        Serial.print(";");

title: Detecting peak frequency in a microphone's output signal

Answers: 0


body:
I am carrying out this project in which the arduino acts as web server and hosts a website in which I show the constantly updated temperature of a laboratory.

The problem is running all this code in the arduino, memory runs out easily.

    void loop() {
      int value= analogRead(PIN_LM35);
      float temperature= value/ 2.046;
      myFile = SD.open("temperature.txt");
      if (myFile) {
        Serial.println(temperature);
        }
        myFile.close();

       EthernetClient client = server.available();
      if (client) {
        while (client.connected()) {
          if (client.available()) {
            char c = client.read();

            //read char by char HTTP request
            if (readString.length() < 100) {
              //store characters to string
              readString += c;
              //Serial.print(c);
             }

             //if HTTP request has ended
             if (c == '\n') {
               Serial.println(readString); //print to serial monitor for debuging

               client.println(F("HTTP/1.1 200 OK")); //send new page
               client.println(F("Content-Type: text/html"));
               client.println();
               refreshcounter=refreshcounter+1;
               client.println(F(""));
               client.println(F(""));
               client.print(F("<meta http-equiv=\"refresh\" content=\"2\">"));
               client.println(F("<meta name='apple-mobile-web-app-capable' content='yes' />"));
               client.println(F("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />"));
               client.println(F("<TITLE>TEMPERATURE SENSOR LAB01</TITLE>"));
               client.println(F(""));
               client.println(F(""));
               client.println(F("
TEMPERATURE SENSOR LAB01
"));
               client.println(F("
"));
               client.println(F("
"));
               client.println(F("
Arduino with Ethernet Shield
"));
               client.println(F("
"));
               if(temperatura<24){
                  client.println("
");
                  client.println(temperature);
                  client.println("
");
               }
               else if(temperature>=24 && temperature<=26){
                 client.println("
");
                 client.println(temperature);
                 client.println("
");
               }
               else{
                 client.println("
");
                 client.println(temperature);
                 client.println(F("
It is recommended to activate the air conditioner.
"));
                 client.println("
");
               }
               client.println(F("
Date/Time:
"));
               client.println(F(""));

               client.println("<svg width=\"1000\" height=\"250\">");
               client.println("<rect width=\"150\" height=\"5\" fill=\"gray\">");
               client.println("<animate attributeName=\"x\" from = \"0\" to =\"10000\" dur=\"10s\" fill=\"freeze\" />");
               client.println("</rect");
               client.println("</svg>");

               client.println("
");
               client.println("");
               client.println("");

               delay(1);
               //stopping client
               client.stop();
                //clearing string for next read
                readString="";

             }
           }
        }
    }
    }

I thought to save memory to put all the code of the web page in an external sd.
However, I don’t really know how to use it from SD card.

The problem that stops me is the fact that the site does not have to be static but constantly updated with new temperature data.

How can I do that?

title: How can I do web hosting having all the code of the site stored in a sd?

Answers: 1

body:
You wrote:
> the site does not have to be static but constantly updated with new
> temperature data.

A good option is to use Ajax.
The basic idea is to split the site in two parts:

- a static part, potentially large, which contains all the user
  interface, the styling, the bells and whistles...
- a tiny, dynamic part that contains the data that is constantly updated
  _and nothing more_.

The static part would be served from the SD card when the client sends a
`GET /` request. The dynamic part would be served from another endpoint,
for example as a reply to `GET /temperature`. Serving the dynamic part
should be very simple, something like:

```c++
client.println(temperature);
```

Yes, just send the number as ASCII, no HTML formatting. If you ever need
to send more than one number (e.g. multiple temperatures, or temperature
and humidity), format them in [JSON][]. No need to use a library for
that, plain `print()` should be cheaper and good enough:

```c++
client.print(F("{\"temperature\":"));
client.print(temperature);
client.print(F(",\"humidity\":"));
client.print(humidity);
client.print('}');
```

On the client side, `JSON.parse()` gets the data back as an easy-to-use
data structure.

Here is a minimal example of what the static part could look like.
Notice the JavaScript code sent to the client. This code is responsible
for querying the temperature every 1000 milliseconds, and updating the
Web page with the new data;

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Ajax test</title>
</head>
<body>

<h1>Ajax test</h1>

<p>Temperature: <span id="temperature">---</span> °C</p>

<script>
var data_field = document.getElementById("temperature");
setInterval(function() {
    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (request.readyState != 4) return;
        data_field.innerText = JSON.parse(request.responseText);
    };
    request.open("GET", "/temperature");
    request.send();
}, 1000);
</script>
</body>
</html>
```

A few notes:

- This example is purposefully minimal. You may want to add some error
  checking, some decorations, some CSS and the such. Handling a
  temperature-dependent color also belongs to the client code.

- The example uses good old `XMLHttpRequest`. You may want to try the
  more modern [fetch API][] instead:

  ```js
  setInterval(function() {
      fetch("/temperature")
          .then(response => response.json())
          .then(data => { data_field.innerText = data; });
  }, 1000);
  ```

- If you are sending updates frequently enough to significantly load
  your Arduino, you may want to look at [Server-sent events][sse]. This
  is a technique that allows you to significantly reduce the overhead of
  sending data updates. It is not as popular as Web-sockets, but has the
  advantage of being simpler to implement server-side.

- If you can put a reverse-proxy between your Arduino and the Internet,
  the proxy can handle the static content. Your Arduino then only
  handles the dynamic data and wouldn't need an SD card. If you
  reverse-proxy Server-sent events, make sure the proxy doesn't buffer
  the server response. See for example these [tips on configuring
  Nginx][nginx] for this purpose.

- The static data could also be served from a completely different Web
  site. For this to work, you have to fulfill two conditions:

  1. The Arduino server has to add the header
     `Access-Control-Allow-Origin: *` to its responses.

  2. On the client code, you have to provide the full URL of the Arduino
     as an argument of `request.open()`, `fetch()` or
     `new EventSource()`.

- The previous trick also allows you to open the Web page directly from
  your local file system, which can be very handy for developing.

- Once you get the basic scheme working, Web technologies allow you to
  get as fancy as you want. You could create an analogue gauge (with SVG
  transform rotate). You could even [add a graph][plotly], updated in
  real time, that shows the time evolution of the temperature, and is
  entirely handled by the client.

[JSON]: https://www.json.org/
[fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
[sse]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
[nginx]:  https://stackoverflow.com/questions/13672743/eventsource-server-sent-events-through-nginx
[plotly]: https://plotly.com/javascript/


body:
im doing a university project where we use 2 IMU sensors and a SD card reader to save the data from sensors.

As you will probably see from the code, we specify the sensor port we listen to, save data to strings and then we open a port to SD reader and save the data.
Everything is in loop.

The problem is we only get around 5Hz (10Hz with only one sensor) - visible by the timer, which is sadly not enough for our project.

I heard about using a fifo buffer, but im not so good at low level programing. Anyway you can help?
Also, do you think removing all Serial.print could help with a little performance boost?

sensors - https://wiki.dfrobot.com/Serial_6_Axis_Accelerometer_SKU_SEN0386#target_0

uCon - Arduino Uno Rev3

```
#include <DFRobot_WT61PC.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

#define FILE_BASE_NAME "Pomiar"
#define VCC2 7

const uint8_t CS_PIN = 4;

SoftwareSerial mySerial(2, 3);
SoftwareSerial mySerial2(5, 6);
DFRobot_WT61PC sensor(&mySerial);
DFRobot_WT61PC sensor2(&mySerial2);

File myFile;
File file;

const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.txt";

void setup()
{

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

  //Use Serial as debugging serial port
  Serial.begin(9600);
  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  while (SD.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      Serial.println(F("Can't create file name"));
      return;
    }
  }

  //Use software serial port mySerial as communication seiral port
  mySerial.begin(9600);
  mySerial2.begin(9600);
  //Revise the data output frequncy of sensor FREQUENCY_0_1HZ for 0.1Hz, FREQUENCY_0_5HZ for 0.5Hz, FREQUENCY_1HZ for 1Hz, FREQUENCY_2HZ for 2Hz,
  //                        FREQUENCY_5HZ for 5Hz, FREQUENCY_10HZ for 10Hz, FREQUENCY_20HZ for 20Hz, FREQUENCY_50HZ for 50Hz,
  //                        FREQUENCY_100HZ for 100Hz, FREQUENCY_125HZ for 125Hz, FREQUENCY_200HZ for 200Hz.
  sensor.modifyFrequency(FREQUENCY_100HZ);
  sensor2.modifyFrequency(FREQUENCY_100HZ);
}

void loop()
{

  long timestamp = millis();

  String acc1 = "";
  String acc2 = "";
  String acc3 = "";
  String gyro1 = "";
  String gyro2 = "";
  String gyro3 = "";
  String angle1 = "";
  String angle2 = "";
  String angle3 = "";

  String acc12 = "";
  String acc22 = "";
  String acc32 = "";
  String gyro12 = "";
  String gyro22 = "";
  String gyro32 = "";
  String angle12 = "";
  String angle22 = "";
  String angle32 = "";

  mySerial.listen();
  if (sensor.available()) {

    acc1 = sensor.Acc.X;
    acc2 = sensor.Acc.Y;
    acc3 = sensor.Acc.Z;
    gyro1 = sensor.Gyro.X;
    gyro2 = sensor.Gyro.Y;
    gyro3 = sensor.Gyro.Z;
    angle1 = sensor.Angle.X;
    angle2 = sensor.Angle.Y;
    angle3 = sensor.Angle.Z;

    Serial.print("Acc\t"); Serial.print(sensor.Acc.X); Serial.print("\t"); Serial.print(sensor.Acc.Y); Serial.print("\t"); Serial.println(sensor.Acc.Z); //acceleration information of X,Y,Z
    Serial.print("Gyro\t"); Serial.print(sensor.Gyro.X); Serial.print("\t"); Serial.print(sensor.Gyro.Y); Serial.print("\t"); Serial.println(sensor.Gyro.Z); //angular velocity information of X,Y,Z
    Serial.print("Angle\t"); Serial.print(sensor.Angle.X); Serial.print("\t"); Serial.print(sensor.Angle.Y); Serial.print("\t"); Serial.println(sensor.Angle.Z); //angle information of X, Y, Z
    Serial.println(" ");
  }

  mySerial2.listen();
  if (sensor2.available()) {

    acc12 = sensor2.Acc.X;
    acc22 = sensor2.Acc.Y;
    acc32 = sensor2.Acc.Z;
    gyro12 = sensor2.Gyro.X;
    gyro22 = sensor2.Gyro.Y;
    gyro32 = sensor2.Gyro.Z;
    angle12 = sensor2.Angle.X;
    angle22 = sensor2.Angle.Y;
    angle32 = sensor2.Angle.Z;

    Serial.print("Acc2\t"); Serial.print(sensor2.Acc.X); Serial.print("\t"); Serial.print(sensor2.Acc.Y); Serial.print("\t"); Serial.println(sensor2.Acc.Z); //acceleration information of X,Y,Z
    Serial.print("Gyro2\t"); Serial.print(sensor2.Gyro.X); Serial.print("\t"); Serial.print(sensor2.Gyro.Y); Serial.print("\t"); Serial.println(sensor2.Gyro.Z); //angular velocity information of X,Y,Z
    Serial.print("Angle2\t"); Serial.print(sensor2.Angle.X); Serial.print("\t"); Serial.print(sensor2.Angle.Y); Serial.print("\t"); Serial.println(sensor2.Angle.Z); //angle information of X, Y, Z
    Serial.println(" ");
  }

  myFile = SD.open(fileName, FILE_WRITE);

  if (myFile) {
    myFile.print(timestamp);
    myFile.print("|");
    myFile.print(acc1);
    myFile.print("|");
    myFile.print(acc2);
    myFile.print("|");
    myFile.print(acc3);
    myFile.print("|");
    myFile.print(gyro1);
    myFile.print("|");
    myFile.print(gyro2);
    myFile.print("|");
    myFile.print(gyro3);
    myFile.print("|");
    myFile.print(angle1);
    myFile.print("|");
    myFile.print(angle2);
    myFile.print("|");
    myFile.print(angle3);
    myFile.println("");

    myFile.print(timestamp);
    myFile.print("|");
    myFile.print(acc12);
    myFile.print("|");
    myFile.print(acc22);
    myFile.print("|");
    myFile.print(acc32);
    myFile.print("|");
    myFile.print(gyro12);
    myFile.print("|");
    myFile.print(gyro22);
    myFile.print("|");
    myFile.print(gyro32);
    myFile.print("|");
    myFile.print(angle12);
    myFile.print("|");
    myFile.print(angle22);
    myFile.print("|");
    myFile.print(angle32);
    myFile.println("");

    myFile.close();
  } else {
    Serial.println("error opening test.txt");
  }
}
```

title: Getting more Hz while working with 3 serial ports (IMU sensors)

Answers: 1

body: There is a memory device called FRAM, It is available in many sizes. I work with 32Kx8 which is under $5.00 US from my favorite china supplier. No write delays, works with SPI or I2C you can get either already mounted on a PCB. For you I would recommend SPI. It is non volatile memory so it will retain the date when power fails. It is good for over 1 trillion cycles.


body:
I activated timer 1 and its interrupt on the 2560 board and it works properly. Now I want to run Timer 4 as well. I installed the Timer 4 library, but when I compile the program, I get the following error. This error also occurs for timers 3 and 5:

    C:\Users\win 8\Documents\Arduino\libraries\Timer5\Timer5.cpp:110:6:
    note: 'void startSlowCountingTimer5()' previously defined here
     void startSlowCountingTimer5(void) {

Thank you for your help.

The full text of the error is as follows
```
C:\Users\win 8\Documents\Arduino\libraries\Timer5\Timer5.cpp: In function 'void startSlowCountingTimer5()':

C:\Users\win 8\Documents\Arduino\libraries\Timer5\Timer5.cpp:127:6: error: redefinition of 'void startSlowCountingTimer5()'

 void startSlowCountingTimer5(void) {

C:\Users\win 8\Documents\Arduino\libraries\Timer5\Timer5.cpp:110:6: note: 'void startSlowCountingTimer5()' previously defined here

 void startSlowCountingTimer5(void) {
```

title: How to use two timers 1 and 4 simultaneously in Arduino Mega 2560

Answers: 1

body:
This is a bug in the library that [was fixed in 2017][pr]! Please
upgrade.

[pr]: https://github.com/carlosrafaelgn/ArduinoTimer/pull/2


body:
I have this code that shows the available sram memory

        int freeRam()
    {
      extern int __heap_start, *__brkval;
      int v;
      return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
    }

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

    void loop()
    {
    }
[![enter image description here][1]][1]

The arduino compiler shows a different value.

* the arduino compiler shows 1856 bytes and
* Serial port shows 1850 bytes

What is the correct value?

  [1]: https://i.stack.imgur.com/AY4l3.jpg

title: Arduino compiler shows different value of sram memory

Answers: 1

body:
Both are correct depending on what value you are interested in. The compiler tells you the size of the global variables. Your code tells you how much memory is free at any one time. Running code requires memory (most often the stack growing to accommodate local variables and the "stack frame" with a copy of the CPU registers in it every time you call a function).

In other words the compiler tells you how much is in your glass when it's handed to you by the barman but your code tells you how much is in there once you have taken a sip.


body:
I'm new to micro-controllers. I've got an ESP32-S3-DevKitC-1 and I'm trying to do a simple hello world with the Serial. I'm using the Arduino IDE for flashing and serial monitoring. My code is:

```
/**
 * As simple as it gets, right? Setup the Serial, wait on it. The periodically print during the loop.
 */
void setup() {
  Serial.begin(9600);   // Initialize serial communications with the PC
  while (!Serial);
}

void loop() {
  Serial.println("Hello World");
  delay(1000);
}
```

I've tried various baud rates. I've also tried a few different configurations for flashing-- this includes flashing over the UART port with upload mode 'UART0/Hardware CDC' and 'USB-OTG CDC (TinyUSB)'. I'm basically at guess and check right now and am looking for some tips or resources to understand the ports. My serial always shows gibberish. I've even tried miniterm like this:

```pyserial-miniterm /dev/cu.usbserial-1410 9600```

title: My ESP32-S3 DevkitC-1 has two USB micro ports labeled 'USB' and 'UART'. What are they for?

Answers: 2

body:
The USB port connects directly to the D+/D- pins of the ESP32, which allows it to act as a USB host. [CircuitPython][1], for instance, uses this functionality to look like a USB flash drive. You could also write software that might have the ESP32 mimic a keyboard or mouse or other simple USB devices over this port. You generally will not use it to program the board, though CircuitPython does install its own firmware updates from files written to the USB flash drive its boot loader presents.

The UART port connects to a USB/serial chip which is connected to the RX and TX pins of the ESP32. If you want to flash firmware to the board in a traditional way (using esptool.py) you'd use this connector. You may need to press the BOOT button to get the device into firmware download mode.

The ESP32 defaults to 115200 baud, which is why you'd see gibberish at 9600 baud - that would be the boot loader messages.

You'll need to ensure that the firmware you're trying to flash to it is built for the correct model CPU and also for the amount of PSRAM on your board. I would stick with 115200 baud for the serial speed so that you'll be able to see the boot loader messages as well as any output of your program, if it's correctly built and flashed to the board. [**edit**: as @hcheung pointed out there is no official stable support for the S3 in the Arduino Core at the time this question was asked]

You can learn more about your device by reading the [official Espressif documentation][2] on it.

  [1]: https://circuitpython.org
  [2]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html

body:
I had to spent some additional time debugging my smart hardware electronics for a home automation wall mount switch based on the ESP32 S3 ( see it on my GitHub [here](https://github.com/aeonSolutions/AeonLabs-Smart-Power-Switch-Outlet/blob/main/README.md) )

[![enter image description here][1]][1]

because I was able to upload the firmware code into it however when reading serial output it only displayed "gibberish" characters.

On the internet I could not find the answer, so I had to work harder to find the solution. Common problems found when dealing with serial output errors are:
- poor UART ground
- absence of a 500 Ohm resistor on the TX line
- UART cable to long
- track coupling and track length mismatch

are all hardware issues that cause serial communication errors and malfunctioning. However, for the ESP32 there's one missing on the list above.
On this particular hardware, I had incorrectly soldered the RTC crystal of 32,768MHz into the MCU crystal place which is for one of 40MHz. The result was, it is possible to do firmware upload using a 32,768Mhz crystal for the MCU however, and due to the incorrect clock frequency, serial output is no longer 115200bps and displays "gibberish" characters.

**In summary make sure the crystal has the correct clock frequency value**.

  [1]: https://i.stack.imgur.com/wACFh.png


body:
Is it possible to ensure that keys (e.g. ssid, ssl certs) are wiped from the memory of a esp32?

I'm new to the esp32, coming from a IoT device security perspective.

Say a person was testing an esp32 application that utilized WIFI, in which sensitive keys are embedded in the firmware. They then overwrote the esp32 with a small led blink firmware in an attempt to clear said keys.

I would like to know if flashing a small "blink" program will be sufficient to remove the keys, so the esp32 could be repurposed without worry that a firmware dump would reveal past firmware information.

This question is specifically targeting scenarios where the esp32 is for development purposes (fuse bits are never burnt - mind I think there is a security flaw where chip can be dumped anyhow).

title: ESP32 Wipe Sensitive Key Data

Answers: 1

body:
You can use `esptool.py` to run an `erase_flash` operation.

> **Erase Flash: erase_flash & erase_region**
>
> To erase the entire flash chip (all data replaced with 0xFF bytes):
>
>     esptool erase_flash
>
> To erase a region of the flash, starting at address 0x20000 with length 0x4000 bytes (16KB):
>
>  esptool erase_region 0x20000 0x4000
>
> The address and length must both be multiples of the SPI flash erase sector size. This is 0x1000 (4096) bytes for supported flash chips.
>
> *-- [esptool basic commands](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/esptool/basic-commands.html)*

As far as copy protection goes you can encrypt the flash contents so even if the chip is read directly without the decryption key they won't be able to make any sense of the data.


body:
For exmaple, I look at the page for [digitalWrite][1] and all I get is this for the signature:

    digitalWrite(pin, value)

No return value type, no paramater type, nothing.

Instead, in a seperate section it says

    Returns
    Nothing

And then it says

    Parameters
    pin: the Arduino pin number.
    value: HIGH or LOW.

What is "value"? An int? uint8_t? bool? Why is the API written in such a weird ambigious way?

I would expect something like

    void digitalWrite(uint8_t pin, uint8_t value)

Like I am used to from other "proper" API documentations.

  [1]: https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/

title: Why are there no clear types given on the Arduino API docs?

Answers: 0


body:
i am transmitting sensor data from my atmega328p to my esp8266. The Sensordata has 3 decimal places. The esp8266 sends this data to my pc and there I see only two digits. This is because the data is saved with two digits in the float variables.
Is there a way to save them with 3? The way to multiply and later to divide does not work because of some issues on my pc server so I need to hand it straight with 3 digits.

title: how to save float with 3 decimal places

Answers: 1

body:
>This is because the data is saved with two digits in the float variables.

No, it's not. It's because `Serial.println()` by default prints only 2 decimal places. You can specify the number of decimal places to print in the function:

    Serial.println(myVal, 3);


body:
I'm working on a battery-powered project. I'm trying to write code, which checks the battery voltage every 30 minutes and changes the color of a LED accordingly. Should I still be using `millis()` or is there a more efficient way to create a timer which tracks these longer time periods? Should I be concerned that the value of millis resets every 50 days, with an example timer like this:

    bool timer(unsigned long &last_time, unsigned long period)
    {
      unsigned long now = millis();
      if (now - last_time >= period) {
        last_time = now;
        return true;
      }
      return false;
    }

title: How to efficiently code a long duration timer

Answers: 4

body:
> Should I still be using millis() or is there a more efficient way to create a timer which tracks these longer time periods?

For longer time periods you really should use an RTC. You will get much better accuracy (assuming accuracy is what you want). You can also use an alarm on the RTC and use it to trigger an interrupt every 30 minutes and wake the MCU from sleep (so as to save precious battery power) to check the voltage.

> Should I be concerned that the value of millis resets every 50 days, with an example timer like this:

Using that method, where you subtract the previous time from the current time, no, there is nothing to worry about. That is the recommended method to work around the wrapping of the millis() count.

body:
There are various notions of efficiency, depending on what resource you
want to optimize for. For a battery-powered project, the most relevant
is likely to be _energy_-efficiency. Then, your code may not be the main
issue.

If you plan for your LED to be turned on continuously, this is going to
significantly tax your battery. Your first concern should then be to
minimize the power drain of the LED itself: make the current through it
as low as convenient, and maybe consider powering it through a DC-DC
converter in order to avoid wasting too much energy in the series
resistor. If your Arduino has a power-indicator LED, you should also
unsolder it. If it has a second microcontroller that it always on (like
the Uno), you should find a way to disable it.

Regarding the energy consumption of the CPU running your code, the only
way to be energy-efficient is to have it sleep most of the time, and
wake it up only when there is useful job to do. Unfortunately, the
Arduino core provides no standard way to sleep. You may have to look
into architecture-specific solutions, or search for a library that
abstracts this for you. On an AVR, for example, you may be able to
significantly lower the consumption by calling
[`sleep_mode()`][avr-libc] once within your `loop()`. This will put your
device in a “shallow” sleep mode, and it will be woken up by the next
timer interrupt (these happen every 1.024 ms). If you want to go to
deep sleep, you will have to arrange a wake-up source other than the
timer interrupt. An RTC could be an option. However, if you do not need
the 30 minute period to be accurate, you may as well use the
watchdog timer (which is ultra-low power) as an interrupt source.

There are many other things to be aware of when you care about power
consumption. I recommend reading [Power saving techniques for
microprocessors][gammon], by Nick Gammon, which covers most of the
relevant issues. Note, however, that it discusses mostly AVR.

[avr-libc]: https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
[gammon]: https://www.gammon.com.au/power

body:
Your posted code **will never fail**.

See <http://gammon.com.au/millis>

Let me put it this way. Does your clock "fail" at midnight?

Subtracting the *start time* from *time now* always works (even after 50 days) because of the way unsigned integers work.

body:
A library I like for this kind of task is Ticker

    #include <Ticker.h>

    void batterycheck() {
        // called by battcheck ticker every 30 minutes
        // read_voltage...
        // set_led_color...
    }

    Ticker battcheck(batterycheck, 30*60*1000, 0);

    setup() {
        battcheck.start();
    }

    loop() {
        battcheck.update();
    }

There's no advantage over doing it manually but I found this library after writing almost exactly the same code for a project that had a bunch of timers running concurrently.


body:
I have a custom CCA that utilizes an ATMEGA328 but with an external clock of 1MHz that I originally burned the ADABOOT bootloader on using an Arduino Nano.  Everything worked as expected, only issue is I noticed the boot up time is a little long and after some research it seems that putting the Opti bootloader on may help with this.

Thus, I am trying to burn the opti bootloader onto my CCA, this time using an Elegoo Uno R3.  I successfully was able to upload the ArduinoISP sketch onto the Uno but when I go to burn the bootloader I get the following error:

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

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

             Using Port                    : COM7
             Using Programmer              : stk500v1
             Overriding Baud Rate          : 19200
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x03
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x03

    avrdude done.  Thank you.

    Error while burning bootloader.

I'm wondering if there is some sort of communication error since my custom CCA has the other bootloader on with different boards.txt settings than the default

f_cpu = 8000000L
upload speed = 7200
low fuse = 0XCB
high fuse = 0xDA
extended fuse = 0xFD

When I perform the loopback test I don't get an echo on the serial monitor.  I see both the "Rx" and "Tx" lights blink on the Uno, not sure if something is up there... Do you need to have a certain sketch uploaded for that to work?

Thanks,
Pete

title: Bootloader Burning Issue

Answers: 0