message:
How can I identify, debug or fix a faulty IMU?

I have an LSM9DS1 breakout board by Sparkfun, and am communicating with it using a Mega 2560 over I2C. The board is given 3.3 V power as defined in the data sheet, though there seems to be confusion whether the SDA and SCL pins need level shifting for communicating with the 5 V Mega. In theory it shouldn't need to.

I am able to connect with the device and get its accelerometer and magnetometer data, however the gyro is just returning noise and no signal. I have dug in to all the registers I know of regarding high pass filters, logging rates, enabling and powering the sensor, but the only hints are that when the gyro is disabled and then polled, it returns a constant nonzero value on all three axes, as though a bit somewhere is stuck. With any other setting the results are unchanged: finite noise on a constant DC signal. Is this even possible? How can I dig deeper to understand and solve this problem?

body:
In theory you **must** use a level shifter for SDA and SCL. The Arduino Mega 2560 board has internal pullup resistors of about 50k for SDA and SCL and extra 10k pullup resistors of 10k to 5V and according to the datasheet the ATmega2560 requires 3.5V to detect a high level for the I2C bus.

Those pullup resistors might damage the LSM9DS1.
5V-3.3V / 50k//10k times two (both SDA and SCL) = 400nA that might be pushed into the sensor (I assume there are protection diodes, and the maximum voltage is 3.6V, therefor the 400nA is just an indication).
I assume the 10k pullup resistors to 3.3V on the sensor module are enabled. They will take away some over-voltage.

The current by the pullup resistors (to 5V) is a very small current, and I don't know if the sensor is in sleep mode during startup.

To be sure you need to buy another LSM9DS1 and a level shifter. Or even better: buy a 3.3V Arduino board, like the Due or the Zero, M0, and so on.

Have to compared the raw sensor data with others ? Those sensors are very noisy. That is why there is so much to do about filter algoritms to get data that can actually be used. The LSM9DS1 does not do processing or smart filtering with the raw data. All you get is the raw data. Did you assume that the values would be zero ? They never will be, because such sensors are far too noisy and too sensitive for that.


sender: user

message:
How can I split data coming from JSON?

In my recent project, I'm working with Arduino and JSON. Now, I get data from JSON and I can able to receive in Arduino side.

Below one is my Arduino code:

    #include<LiquidCrystal.h>

    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

    String response = "";
    bool begin = false;

    void setup()
    {
      Serial.begin(9600);
      lcd.begin(16, 2);
    }

    void loop()
    {

      while(Serial.available() || !begin)
      {
        char in = Serial.read();

        if (in == '{')
        {
          begin = true;
        }

        if(begin) response += (in);

        if(in == '}')
        {
            break;
        }
        delay(1);
      }

      lcd.setCursor(0, 0);
      lcd.print(response);
    }

Output :

    {"TPS":"0.40","MAP":"1.05","LOAD":"14"}

Now, I want to split data means store `0.40` in one variable, `1.05` in another variable and `14` in another variable. I don't know how to split this.

sender: assistant

body:
Finally, I got it. I have fixed length of data. So, I use a counter to calculate the how many characters are there in my data. Now using the index of this characters, I find out proper data and then store in a different variable.

Below is my code:

    #include<LiquidCrystal.h>

    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

    String responseOne = "";
    String responseTwo = "";
    String responseThree = "";
    bool begin = false;

    int counter = 0;

    void setup()
    {
      Serial.begin(9600);
      lcd.begin(16, 2);
    }

    void loop()
    {

      while(Serial.available() || !begin)
      {
        char in = Serial.read();

        if (in == '{')
        {
          begin = true;
        }

        if(begin)
        {
          counter++;

          if(counter >= 9 && counter <= 12)   // This gives 0.40
          {
            responseOne += (in);              // 0.40 store in responseOne variable
          }

          if(counter >= 22 && counter <= 25)  // This gives 1.05
          {
            responseTwo += (in);              // 1.05 store in responseTwo
          }

          if(counter >= 36 && counter <= 37)  // This gives 14
          {
            responseThree += (in);            // 14 store in responseThree
          }
        }

        if(in == '}')
        {
            break;
        }
        delay(1);
      }

      float newResponseOne = responseOne.toFloat();  // Convert string into Float
      float newResponseTwo = responseTwo.toFloat();  // Convert string into Float
      int newResponseThree = responseThree.toInt();  // Convert string into Integer

      lcd.setCursor(0, 0);
      lcd.print(newResponseOne);

      lcd.setCursor(8, 0);
      lcd.print(newResponseTwo);

      lcd.setCursor(0, 1);
      lcd.print(newResponseThree);
    }


message:
Can't send Data to LCD1602 with I2C

I've been doing fine with my LCD1602 I2C configuration but I discovered that command and data functions are the same even though I change the RS command/data bit, but the result is the same.

This is really strange, I really can't do anything about it??!

    #define E   2   // E  bit
    #define RW  1   // RW bit
    #define RS  0   // RS bit

    #define LCDadd_WR  0x4E
    #define LCDadd_RD  0x4F

    uint8_t bitmask = 0x08;
    uint8_t i, arr[]={0x48,0x65,0x6c,0x6c,0x6f ,0x10 ,0x3a,0x29 ,0x10 ,0x48,0x6f,0x77,0x10
    ,0x61,0x72,0x65,0x10,0x79,0x6f,0x75,0x65,0x76,0x65,0x72,0x79,0x10,0x6f,0x6e,0x65};

    // LCD prototypes
    void LCD_Init(void);
    void sendCMD(uint8_t CMD);
    void sendData(uint8_t data);
    void LCD_string(uint8_t arr1[]);
    void move_cursor (uint8_t row, uint8_t col);

    // I2C prototypes
    void I2C_init(void);
    void I2C_start(uint8_t address);
    void I2C_stop(void);
    void I2C_tx(uint8_t data);
    void I2C_TWSR_Check(void);

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

    void loop() {
    //sendData(0x0E); /* I commented this line because it has the same effect as sendCMD(0x0F); in sendCMD function */
    }

    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////
    void LCD_Init(void)
    {
      sendCMD(0x33);
      sendCMD(0x32);
      sendCMD(0x28);
      sendCMD(0x0F);
      sendCMD(0x01);
    }

    void sendCMD(uint8_t CMD)
    {
      bitmask = 0x08;
      I2C_start(LCDadd_WR);
      I2C_tx(bitmask &= ~(1<<RS));
      Serial.println("CMD");
      Serial.println(bitmask, HEX);
      I2C_tx(bitmask &= ~(1<<RW));
      I2C_tx(bitmask = CMD & 0xF0 | 0x08);
      _delay_ms(5);
      I2C_tx(bitmask |= (1<<E));
      _delay_ms(1);
      I2C_tx(bitmask &= ~(1<<E));
      _delay_ms(1);
      I2C_tx(bitmask = (CMD<<4) & 0xF0 | 0x08);
      I2C_tx(bitmask |= (1<<E));
      _delay_ms(1);
      I2C_tx(bitmask &= ~(1<<E));
      I2C_stop();
    }

    void sendData(uint8_t data)
    {
      bitmask = 0x08;
      I2C_start(LCDadd_WR);
      I2C_tx(bitmask |= (1<<RS));
      Serial.println("data");
      Serial.println(bitmask, HEX);
      I2C_tx(bitmask &= ~(1<<RW));
      I2C_tx(bitmask = data & 0xF0 | 0x08);
      _delay_ms(5);
      I2C_tx(bitmask |= (1<<E));
      _delay_ms(1);
      I2C_tx(bitmask &= ~(1<<E));
      _delay_ms(1);
      I2C_tx(bitmask = (data<<4) & 0xF0 | 0x08);
      I2C_tx(bitmask |= (1<<E));
      _delay_ms(1);
      I2C_tx(bitmask &= ~(1<<E));
      I2C_stop();
    }

    uint8_t BF(void)
    {
      I2C_start(LCDadd_WR);
      I2C_tx(bitmask &= ~(1<<RS));
      I2C_tx(bitmask |= (1<<RW));
      I2C_stop();
      I2C_start(LCDadd_RD);
      I2C_rx();
      while (!(TWDR == (bitmask & (bitmask<<3))));
      I2C_stop();
      I2C_start(LCDadd_WR);
      I2C_tx(bitmask |= (1<<RS));
      _delay_ms(500);
      I2C_tx(bitmask &= ~(1<<RS));
      _delay_ms(500);
      I2C_stop();
    }

    void move_cursor (uint8_t row, uint8_t col)
    {
      if (row==1)
      sendCMD(0x80+col);
      if (row==2)
      sendCMD(0xC0+col);
    }

    void LCD_string(uint8_t arr1[])
    {
    uint8_t cnt=0;
      for (i=0;i<29;i++)
      {
        sendData(arr1[i]);
        _delay_ms(500);
        cnt++;
        if (cnt==16)
        sendCMD(0xC0);
      }
      sendData(0x10);
    }

    ///////////////////////////////////////////////////
    ///////////////////////////////////////////////////

    void I2C_init(void)
    {
      //set SCL to 100kHz
      TWSR = 0x00;
      TWBR = 0x48;
      //enable TWI
      TWCR = (1<<TWEN);
    }

    void I2C_start(uint8_t address)
    {
      TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
      while (!(TWCR & (1<<TWINT)));
      TWDR = address;
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
      while (!(TWCR & (1<<TWINT)));
    }

    void I2C_stop(void)
    {
      TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
    }

    void I2C_tx(uint8_t data)
    {
      TWDR = data;
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
      while (!(TWCR & (1<<TWINT)));
    }

    uint8_t I2C_rx(void)
    {
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
      while (!(TWCR & (1<<TWINT)));
      return TWDR;
    }

body:
    I2C_tx(bitmask |= (1<<RS));
    I2C_tx(bitmask &= ~(1<<RW));
    I2C_tx(bitmask = data & 0xF0 | 0x08);

RS is overridden in the third line, so the solution is:

    I2C_tx(bitmask = data & 0xF0 | 0x08 | (1<<RS));

And delete the first two lines :)


message:
Passing user defined callback functions to a library method

I developed an Arduino library that have a method called "process". This method is a Void function and must be called inside the loop and most of the time the library handles everything by it self:

    #include <HookNinja.h>

    HookNinja hookninja;

    void setup()
    {}

    void loop()
    {
      hookninja.process();
    }

The idea is to keep the user program a simple as possible. Sometimes "process" have some data to give back to the user so he can use it as he likes. A simple approach is not to make process void and make the user check for the return value of process:

    void loop()
    {
      someVariableType foo;
      foo = hookninja.process();
      if(foo) {
        //user defined things
      }
    }

But the data returned by process could be anything, from an int to an array of Strings, only the user knows the return type, also this method seems not very elegant. Im not an expert of C++, for me the ideal solution will be an object oriented approach were the user pass a function to process that can be called from the library, but I have no idea how to do this in C++, something like:

    void userFunction(type param) {
      //do something with param
    }

    void loop() {
      hookNinja.process(some how pass userFunction here)
    }

body:
A common solution would be to have the user provide a callback which
takes no arguments and returns nothing. This is how `attachInterrupt()`
works, so it may be the least surprising approach for your users. The
user function can then get data from the rest of the program using
globals.

If you really prefer passing an argument to the user function, the
problem is you do not know the data type. The usual approach in plain C
is to give it a “generic” pointer, and let the user cast it into a
pointer specific for his data type. This is how functions like `qsort()`
work:

<!-- langage: lang-c++ -->

    HookNinja hookninja;

    void userFunction(void *param) {
        someVariableType foo = * (someVariableType *) param;
        //do something with foo
    }

    void setup()
    {
        hookninja.attachCallback(userFunction);
    }

    void loop() {
        someVariableType foo = something;
        hookNinja.process((void *) &foo);
    }

A cleaner C++ approach could be to make you class a template that is
specialized for the type of the user data:

    HookNinja<someVariableType> hookninja;

    void userFunction(someVariableType param) {
        //do something with param
    }

    void setup()
    {
        hookninja.attachCallback(userFunction);
    }

    void loop() {
        someVariableType foo = something;
        hookNinja.process(foo);
    }

But keep in mind that many Arduino users may not be familiar with
templates.


message:
How to light up all LEDs of a 7x5 LED matrix?

I want to light up all the LEDs of a 7x5 matrix with arduino uno. How can i do so?

body:
You don't need an Arduino for that, and one will give you no benefit.

Connect all anodes to power, and all cathodes to the appropriate resistors, then ground.


message:
serial write pixels of a bmp image

I'm looking for a way to read a 24 bpp bmp file from a SD cart, and than convert it to text and write it to the serial monitor.

So the output should look something like this:
R255,B255,G255

And that for each pixel

body: There is no "command" to read BMP files. They're files like any other. If you know how to read files on an SD card with an Arduino, then you know how to read BMP files. *Interpreting* the bytes of the file you just read is another matter. If the details of the BMP (width, height, depth, array offset, etc.) are known already, you may *seek* to the pixel array directly and begin parsing it (in your case, 3 bytes at a time in BGR order), remembering that BMPs are typically arranged bottom-to-top unless the height field in the header is negative.


body:
To read the pixels, start with this:

    int32_t readNbytesInt(File *p_file, int position, byte nBytes)
    {
        if (nBytes > 4)
            return 0;

        p_file->seek(position);

        int32_t weight = 1;
        int32_t result = 0;
        for (; nBytes; nBytes--)
        {
            result += weight * p_file->read();
            weight <<= 8;
        }
        return result
    }

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

        Serial.print("Initializing SD card...");
        if (!SD.begin(53)) {
            Serial.println("initialization failed!");
            while (1); // <- this is how you should block execution, not with returns
        }
        Serial.println("initialization done.");

        // Open
        bmpImage = SD.open("Circle.bmp", FILE_READ);
        textFile = SD.open("test.txt", FILE_WRITE);

        int32_t dataStartingOffset = readNbytesInt(&bmpImage, 0x0A, 4);

        // Change their types to int32_t (4byte)
        int32_t width = readNbytesInt(&bmpImage, 0x12, 4);
        int32_t height = readNbytesInt(&bmpImage, 0x16, 4);
        Serial.println(width);
        Serial.println(height);

        int16_t pixelsize = readNbytesInt(&bmpImage, 0x1C, 2);

        if (pixelsize != 24)
        {
            Serial.println("Image is not 24 bpp");
            while (1);
        }

        bmpImage.seek(dataStartingOffset);//skip bitmap header

        // 24bpp means you have three bytes per pixel, usually B G R

        byte R, G, B;

        for(int32_t i = 0; i < height; i ++) {
            for (int32_t j = 0; j < width; j ++) {
                B = bmpImage.read();
                G = bmpImage.read();
                R = bmpImage.read();
                textFile.print("R");
                textFile.print(R);
                textFile.print("G");
                textFile.print(G);
                textFile.print("B");
                textFile.print(B);
                textFile.print(" ");
            }
            textFile.print("\n");
        }

        bmpImage.close();
        textFile.close();

        Serial.println("done write");
    }`
Source: [Arduino StackExchange Question: How to read bitmap image on arduino](https://arduino.stackexchange.com/questions/19795/how-to-read-bitmap-image-on-arduino)

The text output of this should be a file with an array of strings like `R10G100B25`, where R is the red component of the pixel, G is the green component and B the blue one. Work out how to print these to the serial output.

Note this is only compatible with the 24bpp format.


message:
ESP8266MOD programing using Arduino uno?

I want to make a very simple webserver who sends welcome message to anyone who joins it using WiFi.

I have a ESP8266MOD module, I want to program it using arduino ide and arduino uno board.
How I can use arduino uno to program this WiFi module without using urat USB serial board?

SoftwareSerial.h is not working with esp.write() command, I believe it is because of low power, can anyone suggest me on power supply too?

Thanks in advance,

Mohan

body: When you use the Uno for its UART only, i.e. grounding RST pin, its Rx pin 0 becomes Tx, and Tx pin 1 becomes Rx -- because that's what pins on the UART you are connecting to. AppMonk didn't say what specific breakout/ chip mount he's using, there are many, or say how he's managing level-shifting from the Uno to the ESP if needed. The Tx pin on Uno (0, labeled Rx) is putting out 5v and the ESP would prefer 3.3, so level shifting w/ simple voltage divider is recommended. You don't need to level shift the Tx signal from ESP to Arduino's Rx (pin 1).


message:
LCDs interfere with Adafruit datalogger SD card function

I am using the Adafruit datalogger shield (Rev B) and a pair of cheap 20x4 LCD I2C displays. The displays have a small I2C I/O expansion module board on the back. The LCDs I am using are these;

<https://www.amazon.ca/gp/product/B01GPUMP9C/ref=oh_aui_detailpage_o09_s00?ie=UTF8&psc=1>

I'm using the NewLiquidCrystal 1.3.4 I2C library. My UNO clone is the iteaduino-BT <https://www.itead.cc/iteaduino-bt.html>, which is a board I really like.

I am getting interference between the LCD displays and the SD card function. Sometimes I can write to the SD card, and sometimes I can't. I have tried several SD cards. After a lot of experimenting, I think I have identified the problem. The LCDs are interfering somehow with the SD card functions. The LCD objects are created with the following statements;
<!-- language-all: lang-cpp -->
    // set the lcd1 address to 0x26
    // Set the pins on the I2C chip used for lcd1 connections:
    // addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
    LiquidCrystal_I2C lcd1(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    // set the lcd2 address to 0x27
    LiquidCrystal_I2C lcd2(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

If I comment out the LCD lines, the SD problem goes away. My thinking is that the four data lines used by the LCDs (4,5,6,7) may be overlapping with the datalogger card, but after looking at the datalogger schematic, I can't see the problem. I found a couple of websites suggesting mapping the LCDs to use different data lines, but I'm not sure if that is the problem.

I also ran a program to scan the I2C bus and it showed that the LCDs were at 26 and 27 and the Adafruit datalogger at 68. No interference with addresses at least.

I really need this working yesterday. Creating datalogging projects is nothing new and I can't believe that there is no solution for including I2C LCD displays. Should I experiment with different LCD libraries or try mapping the pins differently during the creation of the LCD objects? I also am wondering if I can simply shut off the LCDs when writing to the SD card and then turn them back on after. I plan on taking measurements and writing the results every 5 minutes for several days, so high speed anything is not a requirement.

The code sample below is part of my program. I use the while(1) line as a hard break for debugging purposes.

    #include <OneWire.h>              // library for DS18B20 thermocouple
    #include <DallasTemperature.h>    // library for DS18B20 thermocouple
    #include <Wire.h>                 // used for rtc
    #include <SD.h>                   // library for SD card
    #include <SPI.h>                  // library used for SD card
    #include <RTClib.h>               // library for real time clock
    #include <LiquidCrystal_I2C.h>    // library for lcd displays
    #define ONE_WIRE_BUS 8            // Data wire for thermocouple is plugged into pin 8 on the Arduino
    #define SYNC_INTERVAL 1000        // mills between calls to flush() - to write data to the card

    RTC_PCF8523 rtc;                  // define the Real Time Clock object

    String datetimestamp;
    uint8_t MM;
    uint8_t DD;
    uint8_t mm;
    uint8_t hh;
    File logfile;                     // create file object to save results on SD card
    const int chipSelect = 10;        // for the data logging shield, we use digital pin 10 for the SD cs line
    OneWire oneWire(ONE_WIRE_BUS);        // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire);  // Pass our oneWire reference to Dallas Temperature.

    // set the lcd1 address to 0x26
    // Set the pins on the I2C chip used for lcd1 connections:
    //                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
    LiquidCrystal_I2C lcd1(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    // set the lcd2 address to 0x27
    LiquidCrystal_I2C lcd2(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    String inputString = "";         // a string to hold incoming data
    String ackString = "ack";        // acknowledgement string from terminal
    String temperature;              // temperature
    boolean stringComplete = false;  // whether the incoming string from serial port is complete with /n
    int interval = 60000;            // interval between measurements
    long previousMillis;
    int cycle = 1;                   // cycle number
    int heartbeat = 30000;           // ping teminal to prevent bluetooth from shutting down
    String dim_length;
    String dim_width;
    String dim_height;
    String measurements;              // string containing measurements for inclusion in SD file
    int firstcomma;
    int secondcomma;
    int thirdcomma;
    String logEntry;
    char filename[] = "logdata.txt";

    void setup(void) {
      Serial.begin(9600);
      inputString.reserve(20);               // reserve space for the inputString
      pinMode(10, OUTPUT);
      pinMode(ONE_WIRE_BUS, INPUT);          // used for thermocouple

      WaitFor(2000);

      lcd1.begin(20, 4);        // initialize the first lcd for 20 chars 4 lines
      lcd1.backlight();         // turn on backlight
      lcd1.clear();             // clear lcd11

      lcd2.begin(20, 4);        // initialize the second lcd for 20 chars 4 lines
      lcd2.backlight();         // turn on backlight
      lcd2.clear();             // clear lcd11

      //These routines update rows on the LCDs
      Row1("DATE: ");
      Row2("TEST CYCLE: ");
      Row3(" ");
      Row4(" ");

      // check for working real time clock
      if (! rtc.begin()) {
        Row4("RTC failed");
        WaitFor(500);
        while (1);
      }
      else {
        Row4("RTC found");
        WaitFor(500);
      }

      if (! rtc.initialized()) {
        Row4("RTC failed");
        WaitFor(500);
        while (1);
      } else {
        Row4("RTC initialized");
        WaitFor(500);
      }

      UpdateRow1(GetTimestamp());      // display current date and time
      UpdateRow2(cycle);               // display current test cycle

      // initialize SD card
      if (!SD.begin(10)) {
        Row4("SD init failed");
        WaitFor(500);
        while (1);
      } else {
        Row4("SD card initialized");
        WaitFor(500);
      }

      //log file setup
      if (SD.exists(filename)) {
        Row4("log file exists");
        WaitFor(500);
      } else {
        Row4("log doesn't exist");
        WaitFor(500);
      }

      // sample write to SD card
      Row4("opening log file");
      logfile = SD.open(filename, FILE_WRITE);
      Row4("writing log file");
      WaitFor(500);
      logfile.println("DateTime,Temperature");
      WaitFor(500);
      for (int x = 1; x < 6; x++) {
        logfile.print("Test # ");
        logfile.println(x);
        delay(1000);
      }
      logfile.flush();
      WaitFor(500);
      Row4("flushed log file");
      WaitFor(1000);

      while (1);  //temporary stop for debugging

body:
I think your problem is with the way you create the LCD instants.

I've always used `LiquidCrystal_I2C lcd(0x27, 20, 4);` `LiquidCrystal_I2C lcd(address, row, col);` when I'm using the I2C modules.


message:
ATmega AVR frequency measurement with timer/counter

I've been rehashing some existing libraries I found on some obscure forums to measure a frequency on digital pin 5, using the ATmega328P/ATmega2560 Timer/Counter modules and an interrupt based approach in order to be able to measure frequencies up to 4MHz(-ish). However, using the code described below, the results are off by a factor of exactly 100. I used a frequency generator to accomplish these readouts. Here is an example of what I've been getting back when generating a 5000Hz square wave (50% duty cycle):

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

Can someone please point out what might be wrong. I've read the ATmega328P datasheet multiple times by now and it should just work! This is very strange.

>**Edit:**
As it turns out the AWG I use has a blantant software bug which causes it to generate a wave with a period that's 100 times too long (see picture below). Nevertheless as Edgar pointed out I made some pretty big mistakes by not taking into account race conditions. Therefore the code below has been updated. Also, the test program has been updated to generate a 50% duty cycle square wave @5000Hz for testing purposes as suggested by Edgar.

[![AWG software bug][2]][2]

This is the header file:

    #ifndef FreqCounter_h
    #define FreqCounter_h

    #include <avr/interrupt.h>
    #if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
    #else
    #include "WProgram.h"
    #endif
    namespace FreqCounter
    {
     extern volatile unsigned long f_freq;
     extern volatile unsigned char f_ready;
     extern volatile unsigned char f_mlt;
     extern volatile unsigned int f_tics;
     extern volatile unsigned int f_period;

     void start(int ms);
    }
    #endif

This is the source file:

    #include <FreqCounter.h>

    volatile unsigned long FreqCounter::f_freq;
    volatile unsigned char FreqCounter::f_ready;
    volatile unsigned char FreqCounter::f_mlt;
    volatile unsigned int FreqCounter::f_tics;
    volatile unsigned int FreqCounter::f_period;

    void FreqCounter::start(int ms) {
        f_period = ms;
     GTCCR = (1<<TSM) | (1<<PSRASY) | (1<<PSRSYNC); //halt all timers

        //set TC1 to normal mode => TOV1 flag set at TOP = 0xFFFF
     TCCR1A &= 0x00; //reset TC1 control register A
        TCCR1B &= 0x00; //reset TC1 control register B

        //set TC1 to use external clock source, clocked on rising edge
     TCCR1B |= (1<<CS10);
        TCCR1B |= (1<<CS11);
        TCCR1B |= (1<<CS12);

     //reset TC2
        TCCR2A &= 0x00; //reset TC2 control register A
        TCCR2B &= 0x00; //reset TC2 control register B

     //set TC2 to CTC Mode with TOP = OCR2A => counter cleared on reaching TOP
     TCCR2A |= (1<<WGM21);

     //TC2 is in CTC mode => set value of OCR2A = TOP
     OCR2A = 124; //TOP is reached every 125 counts (starting from 0)

        //set TC2 to use a prescaler of 1 => 16MHz / 128 = 125kHz
        TCCR2B |= (1<<CS20);
        TCCR2B |= (1<<CS22);

        f_ready = 0; //reset ready flag
        f_tics = 0; //reset TC2 interrupt counter

     //synchronize the value of both timers
        TCNT2 = 0;
        TCNT1 = 0;

        //clear interrupt flags
     TIFR2 |= (1<<OCF2A);
     TIFR1 |= (1<<TOV1);

        TIMSK2 |= (1<<OCIE2A); //enable TC2 Output Compare A interrupt => triggered on reaching TOP = OCR2A
     TIMSK1 |= (1<<TOIE1); //enable TC1 overflow interrupt => triggered on reaching TOP = MAX = 0xFFFF

     GTCCR &= 0x00; //restart all timers => start counting
    }

    /*
     * This ISR is triggered by TC2 every 1ms because
     * TC2 increments with a frequency of 16MHz / 128 = 125KHz
     * and reaches TOP every 125 counts
     * => trigger frequency = 1kHz
     * => trigger period = 1ms
     *
     * This ISR handles the Gate Time generation
     */
    ISR(TIMER2_COMPA_vect)
    {
        //increment number of TC2 interrupts (triggers when reaching TOP = OCR2A)
     FreqCounter::f_tics++;

     /*
      * If branch evaluates as true if given gate time (f_period) equals
      * amount of milliseconds TC2 has counted (= f_tics)
      */
     if (FreqCounter::f_tics >= FreqCounter::f_period)
     {
      //end of gate time => measurement ready
      TCCR1B &= ~0x07; //set TC1 to no clk source => TC1 stops counting
      TIMSK2 &= ~(1<<OCIE2A); //disable TC2 Output Compare A interrupt
      TIMSK1 &= ~(1<<TOIE1); //disable TC1 overflow interrupt
      FreqCounter::f_ready = 1; //set software flag for end of gating period

            //increment on overflow of TCNT1
      if (bit_is_set(TIFR1, TOV1))
       FreqCounter::f_mlt++;

            //calculate frequency
      FreqCounter::f_freq = 65536 * FreqCounter::f_mlt;
      FreqCounter::f_freq += TCNT1; //add value of TC1
      FreqCounter::f_freq = (long)(FreqCounter::f_freq * 1000.0 / (double)FreqCounter::f_tics);
      FreqCounter::f_mlt = 0;
        }
    }

    ISR(TIMER1_OVF_vect)
    {
     FreqCounter::f_mlt++;
    }

This is the test program:

    #include <FreqCounter.h>

    long frq;

    void setup()
    {
        //generate a 5 kHz square wave on OC0B = digital pin 5 = T1
     DDRD |= _BV(PD5); //PD5 = OC0B as output
     TCCR0B = 0; //stop timer
     TIMSK0 = 0; //disable overflow interrupt
     OCR0A = 50 - 1; //period = 50 * 64 cycles
     OCR0B = 50 / 2 - 1; //50% duty cycle
     TCCR0A = _BV(COM0B1) //non-inverting PWM on OC0B
      | _BV(WGM00) //fast PWM, TOP = OCR0A
      | _BV(WGM01); //...ditto
     TCCR0B = _BV(WGM02) //...ditto
      | _BV(CS00) //clock at F_CPU / 64
      | _BV(CS01); //...ditto
     Serial.begin(57600);
     Serial.println("Frequency Counter");
    }

    void loop()
    {
     FreqCounter::start(1000);
     while (FreqCounter::f_ready == 0);
     frq = FreqCounter::f_freq;
     Serial.println(frq);
    }

PS: This is my first ever post on this forum. Feel free to comment on the contents of my question. Tips as to how I might improve future questions are always welcome. Have a great day!

  [1]: https://i.stack.imgur.com/HQPLB.png
  [2]: https://i.stack.imgur.com/5rsZC.png

body:
I am posting this as an answer, just because it doesn't fit as a
comment. But more than an answer it is intended to be a debugging help.

First, I would like to point out that you can use the same Arduino to
both generate the test signal and read it. This can be done by
configuring Timer 0 (the last one you have left...) to output the 5 kHz
square wave on OC0B (digital pin 5), and wire this signal to pin T1
which is... also digital 5. No wiring needed then! You can do this by
adding the following to your test program's `setup()`:

    // Generate a 5 kHz square wave on OC0B = digital pin 5.
    DDRD  |= _BV(PD5);    // PD5 = OC0B as output
    TCCR0B = 0;           // stop timer
    TIMSK0 = 0;           // disable overflow interrupt
    OCR0A  = 50 - 1;      // period = 50 * 64 cycles
    OCR0B  = 50/2 - 1;    // 50% duty cycle
    TCCR0A = _BV(COM0B1)  // non-inverting PWM on OC0B
           | _BV(WGM00)   // fast PWM, TOP = OCR0A
           | _BV(WGM01);  // ...ditto
    TCCR0B = _BV(WGM02)   // ...ditto
           | _BV(CS00)    // clock at F_CPU / 64
           | _BV(CS01);   // ...ditto

Then I would like to point out a couple of bugs in the library you are
using. First, there is an off-by-one error: the program is counting one
millisecond too much. This can be fixed by moving the lines

    //increment number of TC2 interrupts (triggers when reaching TOP = OCR2A)
    FreqCounter::f_tics++;

from the bottom to the top if `ISR(TIMER2_COMPA_vect)`.

Next, there is a race condition between the ISRs. Race conditions are
nasty bugs because they are hard to reproduce and most of the time you
don't see them. And then the program just fails at a random time after
many tests showed it works fine.

Here it works as follows: let's say that after the required time has
elapsed, `TIMER2_COMPA` fires and _right after that_ `TIMER1_OVF` fires
also. This second interrupt is put on hold (it's a _pending interrupt_)
while `TIMER2_COMPA_vect` runs through its prologue. Then you compute
the frequency based on `FreqCounter::f_mlt` (which has not been updated
to account for the overflow) and `TCNT1` (which has already overflown to
zero). Thus you get an incorrect result. Not only that, the overflow
flag remains set, so the ISR will run _right away_ as soon as the
interrupt is enabled again by your next call to `FreqCounter::start()`.
And again you get an incorrect result.

The fix is two fold: first you have to detect the pending interrupt
condition in `ISR(TIMER2_COMPA_vect)`: after stopping the timers and
before computing `FreqCounter::f_freq`, you need this:

    // Did we miss an overflow?
    if (bit_is_set(TIFR1, TOV1))
        FreqCounter::f_mlt++;

Next, you have to clear the interrupt flag. This is customarily done
right before enabling the interrupt, and just to be safe you do it for
every interrupt you enable. Thus, in `FreqCounter::start()`, right
before touching `TIMSK2` and `TIMSK1`, you would:

    // Clear interrupt flags.
    TIFR2 = _BV(OCF2A);
    TIFR1 = _BV(TOV1);

There are a couple of other minor issues, like the statement
`TCCR2A &= ~(1<<WGM22);` which makes no sense (the bit belongs to
another register). But given that this, like a few other statements, has
no effect whatsoever, it should not affect the working of the program.
It does reveal sloppy programming though.


message:
ESP8266 problem with recieved data trasmission via TCP

I am having small project where I want to read couple of analog inputs from Arduino UNO, send it via software serial to ESP8266-01 and from that to python server using TCP.

Data is sent to ESP using this code on Arduino UNO

    #include <SoftwareSerial.h>

        SoftwareSerial mySerial(10, 11); // RX, TX
        int pin = 5;

        void setup() {
          mySerial.begin(9600);
          delay(20000);
        }
        void loop() {
          delay(1000);
          int data = analogRead(pin);
          mySerial.println(data);
        }

Code on ESP is bellow

    void loop() {
        while(Serial.available()>0){
        char data = Serial.read();
        client.print(data);
        }
    }

When data is sent to Python server, it prints it out but data is sent in two seperate parts, so it always looks like this

    9
    59

, but number sent from arduino is just 959!

Python server code snipet:

    while True:

            #Receiving from client
            data = conn.recv(1024)

            print data

            #send data to database
            post.create(
                current = str(data)
            )

             if not data:
                break

So the question is, why data sent to server is separated in two parts? Maybe it have to do something with how data is reading from serial on esp?

body:
You assume all 5 bytes of `959\r\n` are received by the server at the same time. The data is sent byte after byte, based on the `client.print(data)` in the ESP code and assuming the underlying library doesn't buffer bytes before transmitting, so there's no way they'll arrive at the server simultaneously. Most likely, your first pass with `conn.recv(1024)` grabs the first byte `9` and times out. And then on the second pass, the others (at least 2) arrive and are read. The newline between the packets is typical Python 2 `print` behaviour.

What you need to do is parse the data at the server. Basically read data till you get CRLF i.e. `\r\n`, which is a good enough delimiter and you're sending it already anyways, and then use that to know when to write to your database.


message:
Data logging speed with arduino

I am trying to make some data logging conserining physiological data coming from a bitalino.
My problem is that I would like to collect samples at something like 1 kHz, that is the rate that the bitalino can read the sensors, but I think that the time needed
to write this data to the SD card can't keep up with the speed, and here is why i think that:

I put in the script some timers to check what was consuming the time causing to low sample rate, resulting:

    Bitalino: 0, SD: 27
    Bitalino: 0, SD: 28
    Bitalino: 2, SD: 26
    Bitalino: 0, SD: 29

Being that the time in miliseconds.

    void loop() {
        time = millis();
        readBIT();
        time2 = millis();
        printDataSD();
        time3 = millis();
        printData();
    }

    void printData() //Send the data acquired to the pc through the serial port
    {
      Serial.print("Bitalino: ");
      Serial.print(time2-time);
      Serial.print(", SD: ");
      Serial.println(time3-time2);
    }

    void printDataSD() //Send the data acquired to the SD Card
    {
        if (myFile) {
        //Bitalino
        myFile.print(_ECG);
        myFile.print(",");
        myFile.print(_EMG);
        myFile.print(",");
        myFile.print(_EEG);
        myFile.print(",");
        myFile.print(_EDA);
        myFile.print(",");
        //Time
        myFile.println(time);
        myFile.flush();

        } else {
        Serial.print("error opening file, ");
        SD.begin(10);
        delay(1000);
      }
    }
I would like to know if there is a way to improve my sample rate.

Thank you!

Here is the readBit() like asked:

    void readBIT() //Read IMU data
     {
      _ECG = analogRead(ECG);
      _ECG = ((_ECG/1024) - 0.5)*Vcc*1000/gECG; //mV

     _EMG = analogRead(EMG);
     _EMG = ((_EMG/1024) - 0.5)*Vcc*1000/gEMG; //mV

     _EEG = analogRead(EEG);
     _EEG = ((_EEG/1024) - 0.5)*Vcc*1000000/gEEG; //uV

     _EDA = analogRead(EDA);
     _EDA = (_EDA/1024*Vcc-0.259388)/gEDA; // revolution
     }

body:
Why not write a simple program and try to write values like 1, 2, 3 ... 100 to the SD card with a 1 second delay between writes. Then read the values back and send them via serial link to your PC screen.
This way you can make sure that you are writing and reading values in the correct way.

Once this works, you can reduce the delay and see what is the minimum delay between writes that the SD card will support.

It might be advisable to also write a program to fill the SD card with 100 values = 0 to clear it before the next test.


body:
The OP has likely solved this problem by now, but I know that others will be in the same position, so I am answering for them.

I routinely record ten channels of biological sensors including one of 16-bit sound at 8 kHz (plus the associated FFT data) to an SD card using arduino-compatible systems, so I doubt very much that the SD card writing per se is the problem.

Throughput to an SD card is a function of several variables.

 - To maximize write throughput you need to write full blocks of data at
   the correct block size, since partial blocks take the same amount of
   time as full blocks.
 - You also need to be ready with more data as soon as the SD card is
   ready to take more, otherwise precious cycles slip away from you.
 - You need to ensure that your writes are non-blocking (don't try to
   write more than the buffer can receive) so your loop can process and
   queue up new data while the SD card is doing its thing.
 - You need to read any timing-sensitive sensors using interrupt service
   routines that write their data either to a circular buffer or to one
   of a group of two or three buffers that are cycled between being
   filled and being emptied.

Printing debug statements to the serial port can take many tens of milliseconds in a loop that otherwise may take only a few microseconds. If you write more than the serial port buffer can hold, the call will be blocking and you will be at the mercy of the PC that's reading the serial port. This will always be bad enough to mess up the program you're trying to debug... I've encountered situations where this introduced delays of up to 10 seconds (the PC was misbehaving, but still...).

A quick improvement to printing debug statements is to maintain a loop counter and only print a debug statement every N loops.

The program in the original question uses a naive strategy in the sense that it acquires some amount of data and then immediately tries to write it to the SD card, waiting until the write is complete before trying to acquire new data. This will never work at high data rates for the reasons given above. If you use this approach, you are likely wasting 90% of your program cycles in waiting for the SD write and the Serial port write. If either one takes too long, you will miss the next data acquisition window.

My advice: your first step is to research and find or write a circular buffer library.

Then set a timer to call an interrupt service routine that acquires data and puts it into the circular buffer.

Write a loop routine that checks to see whether the SD card is available for writing, and then takes just enough data out of the circular buffer to fit in a single block write for your SD card (look at the documentation for the card adaptor and the card).

At that point you will know whether your system can keep up with your needs.

It's possible that your SD card writing itself is OK but your Arduino is having trouble keeping up either because it's too slow or because you don't have enough room for a sufficiently large circular buffer. I doubt this because I've recorded and played back audio at 8 KHz on the Uno, but then I don't know what else you need to accomplish in your program.

If you do determine that the Arduino itself is too slow or has insufficient memory, take a look at the Teensy series of boards[ \[https://www.pjrc.com/teensy/index.html\]][1]. They are entirely compatible with Arduino libraries and IDE but they run hundreds of times faster than the Uno at a larger data width, plus they have oodles of RAM and a gazillion pins. They're also much smaller than the Arduino form factor and the community that uses them is very knowledgeable.

If it turns out that SD card write throughput is OK but that it requires more buffering than you have on-board, you can add an SPI ram breakout board for more fast buffering space.

Finally, if the amount of data you need to collect is so large and so continuous that you simply can't buffer it long enough to get it written out to SD, or if the SD card truly can't keep up, or if the data is larger than any available SD card, you may consider sending your data off the board in near-real-time. I send 10 hours of nightly data from a Teensy over a USB virtual serial port to the PC at about 3Mbps, and others have done better. Ethernet output is also available and can be at least an order of magnitude greater.

glhf!

  [1]: https://www.pjrc.com/teensy/index.html


message:
Turn LEDs on in binary sequence

Could I have some help getting the following code work?

My purpose is to turn on 4(or N) LEDs in a binary sequence with 4 (or N) bits, A,B,C,D. When bit=1, LED on, otherwise LED off,...

I will have 16 combinations, 2^4=16, so:

 - 0000 => All leds off
 - 0001 => All leds off except the one on the right
 - ...

Here's the code I came up with:

    int LEDblu=4;
    int LEDgiallo=2;
    int LEDrosso=5;
    int LEDverde=7;
    int num_led;
    String numeri="";
    String output;
    int i=0;
    int p;

    void setup() {
        // put your setup code here, to run once:
        pinMode(LEDblu,OUTPUT);
        pinMode(LEDgiallo,OUTPUT);
        pinMode(LEDrosso,OUTPUT);
        pinMode(LEDverde,OUTPUT);

        Serial.begin(9600);

        if(Serial.available())                //Dimmi numero LED
        {
            num_led=Serial.readString().toInt();
            Serial.print(num_led);
        }
    }

    void loop() {
        // put your main code here, to run repeatedly:
        int vect[num_led];
        for(int i=num_led-1, c=0; i>=0; i--, c++)
        {
            int num=2^i;
            vect[c]=num;
        }

        output="";

        if(i<2^num_led)
        {
            p=i;

            for(int c=0; c<num_led; c++)     //Convert binary to decimal
            {
                if(p>=vect[c])
                {
                    output+="1";
                    int d=vect[c];
                    p-=d;
                }
                else
                    output+="0";
            }

            Serial.println(output);

            if(output[0]=="1")
                digitalWrite(LEDrosso,HIGH);
            else
                digitalWrite(LEDrosso,LOW);

            if(output[1]=="1")
                digitalWrite(LEDverde,HIGH);
            else
                digitalWrite(LEDverde,LOW);

            if(output[2]=="1")
                digitalWrite(LEDgiallo,HIGH);
            else
                digitalWrite(LEDgiallo,LOW);

            if(output[3]=="1")
                digitalWrite(LEDblu,HIGH);
            else
                digitalWrite(LEDblu,LOW);
        }

        delay(1000);
        i++;
    }

body:
I don't see any specific initialization of `num_led`; it should be set to some appropriate value, like 4.

As noted in some comments, the `^` operator is bitwise exclusive-Or.  For example, 2^2 is 0, 2^4 is 6, 2^7 is 5, etc.

To compute the nth power of 2, say `1<<n`.

Your convert-binary-to-decimal code is clunky and unnecessary.  Instead, do something like the following, which repeatedly strips off the least significant bit of `t`:

    t = p;
    digitalWrite(LEDrosso,t&1);   t>>=1;
    digitalWrite(LEDverde,t&1);   t>>=1;
    digitalWrite(LEDgiallo,t&1);  t>>=1;
    digitalWrite(LEDblu,t&1);

If you want the blue LED instead of the red one to represent the least significant bit, reverse the order of color names in the `digitalWrite` statements from rosso, verde, giallo, blu to blu, giallo, verde, rosso.

To print data out in binary, use the [`Streaming.h`](http://arduiniana.org/libraries/streaming/) library, and say, for example,

    Serial << _BIN(p) << endl;


body:
Note that this is one of those situations where [direct port access][]
just makes things easier. You did not specify what board you are using,
and I will assume you have some AVR-based board. On those boards, I/O
pins come in groups called _ports_, with up to eight pins per port. You
can update all the pins of a port at once by writing a number to the
port output register. And guess what? The number you write comes out the
pins in binary, jut like everything works in binary inside the
microcontroller.

For example, on an Arduino Uno, you could wire your LEDs to the first
four pins of port B: i.e. pins 8 (lest significant bit) through 11 (most
significant bit). Then you can output a number to the LEDs just by
writing `PORTB = number`, and your loop would become:

<!-- language: lang-c++ -->

    void loop()
    {
        static uint8_t number;
        PORTB = number;              // output to pins 8..11
        Serial.println(number, 2);   // print the value in binary
        number = (number + 1) % 16;  // increment modulo 16
        delay(1000);
    }

[direct port access]: https://www.arduino.cc/en/Reference/PortManipulation


message:
Why is the SPI response mis-ordered?

I have a Raspberry Pi and an Arduino Micro. The two are connected by a SPI bus, the RPi is the master; the Arduino the slave.

I need to send 5 bytes to the Arduino and get 5 bytes as an answer.
The answer is pre-calculated so when the Arduino receives the first byte, it already knows what to answer.

I don't understand why the response I get is mis-ordered. I get the right bytes (value), but they seem shifted in time.

Arduino code:

<!-- language: c++ -->

    // Data received
    volatile unsigned char rx_buffer[5];

    // Data to be sent
    volatile unsigned char tx_buffer[5];

    // Triggered to true by the interruption when message is complete
    volatile bool message_ready(false);

    // Useful to keep trace of where we are in the message
    unsigned char bytes_received = 0;

    // SPI interrupt routine
    // Message consists of 5 bytes: never less, never more
    ISR (SPI_STC_vect)
    {
      SPDR = tx_buffer[bytes_received];
      rx_buffer[bytes_received] = SPDR;

      if (++bytes_received == 5) // Reached the end of the buffer
      {
        bytes_received = 0;
        message_ready = true;
      }
    }

    void setup (void)
    {
      pinMode(MISO, OUTPUT); // Set Slave Output as output
      SPCR |= _BV(SPE); // Slave mode
      SPCR |= _BV(SPIE); // Turn on interrupts

      // Reponse to be sent
      tx_buffer[0] = 'a';
      tx_buffer[1] = 'b';
      tx_buffer[2] = 'c';
      tx_buffer[3] = 'd';
      tx_buffer[4] = 'e';
    }

    void loop (void)
    {
      // When message is ready, print it on serial port
      if (message_ready)
      {
        message_ready = false;
        Serial.print((char) rx_buffer[0]);
        Serial.print((char) rx_buffer[1]);
        Serial.print((char) rx_buffer[2]);
        Serial.print((char) rx_buffer[3]);
        Serial.println((char) rx_buffer[4]);
      }
    }

The RPi uses a C++ program and WiringPi 2.39 to communicate (I also made a similar program with Unix spidev/ioctl calls, same results)

<!-- language: c++ -->

    #include <iostream>
    #include <thread>
    #include <chrono>

    #include <wiringPi.h>
    #include <wiringPiSPI.h>

    using std::cout;
    using std::cerr;
    using std::endl;

    int main(void)
    {
      // Initialize wiringPi
      if (!wiringPiSPISetup(0, 150000))
      {
        cerr << "Could not initialize SPI!" << endl;
        return 1;
      }

      // Create message and response arrays
      uint8_t message[5], response[5];
      message[0] = 'z';
      message[1] = 'u';
      message[2] = 't';
      message[3] = ' ';
      message[4] = '!';

      std::chrono::steady_clock::time_point begin, end;
      unsigned count(0);
      while (1)
      {
        // Change the number at the end of the message: "zut 0", "zut 1" etc..
        message[4] = *std::to_string(count++).c_str();
        if (count == 10)
          count = 0;

        // Copy the message into response because reponse is going to be overwritten
        for (unsigned i(0); i < 5; ++i)
          response[i] = message[i];

        // Count time and transfer the message (and get the reponse at the same time)
        begin = std::chrono::steady_clock::now();
        if (!wiringPiSPIDataRW (0, response, 5))
          cerr << "Could not send message!" << endl;
        end = std::chrono::steady_clock::now();

        // Inform user
        cout << "Sent: " << message << endl;
        cout << "Received: " << response << endl;
        cout << "Duration: " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << " microseconds" << endl;

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      }

      return 0;
    }

The outputs are the following,

Arduino (read over serial):

    zut 0
    zut 1
    zut 2
    zut 3
    zut 4
    zut 5
    zut 6
    zut 7
    zut 8
    zut 9
    zut 0
    zut 1
    zut 2
    zut 3

Everything looks good on the Arduino receive side!

RPi output (std::cout/cerr):

    Sent: zut 0
    Received: eabcd
    Duration: 374 microseconds

    Sent: zut 1
    Received: eabcd
    Duration: 359 microseconds

    Sent: zut 2
    Received: eabcd
    Duration: 357 microseconds

    Sent: zut 3
    Received: eabcd
    Duration: 384 microseconds

    Sent: zut 4
    Received: eabcd
    Duration: 389 microseconds

    Sent: zut 5
    Received: eabcd
    Duration: 384 microseconds

    Sent: zut 6
    Received: eabcd
    Duration: 386 microseconds

    Sent: zut 7
    Received: eabcd
    Duration: 391 microseconds

    Sent: zut 8
    Received: eabcd
    Duration: 385 microseconds

    Sent: zut 9
    Received: eabcd
    Duration: 387 microseconds

    Sent: zut 0
    Received: eabcd
    Duration: 387 microseconds

    Sent: zut 1
    Received: eabcd
    Duration: 387 microseconds

    Sent: zut 2
    Received: eabcd
    Duration: 390 microseconds

    Sent: zut 3
    Received: eabcd
    Duration: 386 microseconds

I get the bytes `eabcd` but I expected `abcde`.

Why isn't the RPi receiving the bytes in the correct order? Don't hesitate to ask for additional information.

body:
@KIIV gave me the answer:

> Anyway to not be shifted, you'll have to fill the data register in slave device BEFORE master even starts the transfer.

What happens is that when an SPI transfer is complete, we enter the `ISR (SPI_STC_vect)`, this means that 1 byte (8 bits) has been received. This also means that the response has been sent, because SPI is full duplex!

So the `SPDR` must be filled with the next byte to be sent before entering the ISR. If you modify the `SPDR` inside the ISR, this will set the next byte to be sent; it will not be sent until a byte is received.

----------

# Fixed Arduino code

<!-- language: c++ -->

    // Data received
    volatile unsigned char rx_buffer[5];

    // Data to be sent
    volatile unsigned char tx_buffer[5];

    // Triggered to true by the interruption when message is complete
    volatile bool message_ready(false);

    // Useful to keep trace of where we are in the message
    unsigned char bytes_received = 0;

    // SPI interrupt routine
    // Message consists of 5 bytes: never less, never more
    ISR (SPI_STC_vect)
    {
      // Store incoming byte
      rx_buffer[bytes_received] = SPDR;

      if (++bytes_received == 5) // Reached the end of the message/buffer
      {
        bytes_received = 0;
        message_ready = true;

        // Let's send another message next time!
        changeTxMessage();
      }

      // When next byte is received, this will be the response
      SPDR = tx_buffer[bytes_received];
    }

    // This changes the response message sent by the Arduino to the RPi
    unsigned count(0);
    void changeTxMessage()
    {
      // Update message
      switch (count++)
      {
        case 0:
          tx_buffer[0] = 'c';
          tx_buffer[1] = 'r';
          tx_buffer[2] = 'a';
          tx_buffer[3] = 'z';
          tx_buffer[4] = 'y';
          break;
        case 1:
          tx_buffer[0] = 'k';
          tx_buffer[1] = 'a';
          tx_buffer[2] = 'n';
          tx_buffer[3] = 'j';
          tx_buffer[4] = 'i';
          break;
        case 2:
          tx_buffer[0] = 'b';
          tx_buffer[1] = 'u';
          tx_buffer[2] = 'x';
          tx_buffer[3] = 'o';
          tx_buffer[4] = 'm';
          break;
      }

      if (count > 2)
        count = 0;
    }

    void setup (void)
    {
      pinMode(MISO, OUTPUT); // Set Slave Output as output
      SPCR |= _BV(SPE); // Slave mode
      SPCR |= _BV(SPIE); // Turn on interrupts

      // Reponse to be sent
      tx_buffer[0] = 'a';
      tx_buffer[1] = 'b';
      tx_buffer[2] = 'c';
      tx_buffer[3] = 'd';
      tx_buffer[4] = 'e';

      // Prepare first byte to be sent as a response
      SPDR = tx_buffer[0];
    }

    void loop (void)
    {
      // When message is ready, print it on serial port
      if (message_ready)
      {
        message_ready = false;
        Serial.print((char) rx_buffer[0]);
        Serial.print((char) rx_buffer[1]);
        Serial.print((char) rx_buffer[2]);
        Serial.print((char) rx_buffer[3]);
        Serial.println((char) rx_buffer[4]);
      }
    }

Changes done:

 - On setup(), `SPDR` is filled with the first response byte
 - Added a new function `void changeTxMessage()` that changes the response message sent by the Arduino for demo purposes.

Arduino output:

    zut 0
    zut 1
    zut 2
    zut 3
    zut 4
    zut 5

RPi output:

    Sent: zut 0
    Received: abcde
    Duration: 241 microseconds
    Sent: zut 1
    Received: crazy
    Duration: 231 microseconds
    Sent: zut 2
    Received: kanji
    Duration: 232 microseconds
    Sent: zut 3
    Received: buxom
    Duration: 249 microseconds
    Sent: zut 4
    Received: crazy
    Duration: 254 microseconds
    Sent: zut 5
    Received: kanji
    Duration: 254 microseconds

Everything looks good!

----------
# Further thoughts

One thing I don't understand with the old code: why did I receive `eabcd` the first time I get an answer, the first byte should be random because I did not set the SPDR?! Maybe it's kept in memory during Arduino upload.

----------
# Performance

I cannot achieve high bit rates with this code. 250 000 Hz is the maximum I can reach (`wiringPiSPISetup(0, 250000)`) before getting problems in the communication. Example at 0.5 Mhz:

Arduino log:

    zut 0
    zut 1
    zut 2
    zut 3
    zut 4
    zut 5
    zut 6
    zut 7

RPi log:

    Sent: zut 0
    Received: bzut
    Duration: 143 microseconds
    Sent: zut 1
    Received: czut
    Duration: 136 microseconds
    Sent: zut 2
    Received: kzut
    Duration: 135 microseconds

I expected to reach at least 2 Mhz, I think I'll open a new question for that.


message:
7 segment displays arduino mega 2560

I'm trying to use an Arduino Mega 2560 to use 7-segment displays, 6 displays... I use 3 CD4543B to pilot the 6 displays.

It works very well for 4 displays as you can see in this [video][1].

But when I want to use the same circuit for 5 or 6 displays, there is some bug as you can see on this [video][2] for 5 displays.

Here is the code that works fine for 4 displays:

    //définition des broches du premier décodeur
    const int bit_A=8;
    const int bit_B=9;
    const int bit_C=10;
    const int bit_D=11;
    //définition du brochage du deuxieme decodeur
    const int bit_E=22;
    const int bit_F=24;
    const int bit_G=26;
    const int bit_H=28;
    //définition du brochage du 3ième décodeur
    const int bit_I=40;
    const int bit_J=42;
    const int bit_K=44;
    const int bit_L=46;
    //définition des broches des transistors

    const int alim_millier=3;
    const int alim_centaine=4;
    const int alim_dizaine=5;
    const int alim_unite=6;

    void setup() {
      //les broches sont toutes des sorties
      pinMode(bit_A,OUTPUT);
      pinMode(bit_B,OUTPUT);
      pinMode(bit_C,OUTPUT);
      pinMode(bit_D,OUTPUT);
      pinMode(bit_E,OUTPUT);
      pinMode(bit_F,OUTPUT);
      pinMode(bit_G,OUTPUT);
      pinMode(bit_H,OUTPUT);
      pinMode(bit_I,OUTPUT);
      pinMode(bit_J,OUTPUT);
      pinMode(bit_K,OUTPUT);
      pinMode(bit_L,OUTPUT);
      pinMode(alim_millier,OUTPUT);
      pinMode(alim_centaine,OUTPUT);
      pinMode(alim_dizaine,OUTPUT);
      pinMode(alim_unite,OUTPUT);
      //les broches sont toutes mises à l'état bas
      digitalWrite(bit_A,LOW);
      digitalWrite(bit_B,LOW);
      digitalWrite(bit_C,LOW);
      digitalWrite(bit_D,LOW);
      digitalWrite(bit_E,LOW);
      digitalWrite(bit_F,LOW);
      digitalWrite(bit_G,LOW);
      digitalWrite(bit_H,LOW);
      digitalWrite(bit_I,LOW);
      digitalWrite(bit_J,LOW);
      digitalWrite(bit_K,LOW);
      digitalWrite(bit_L,LOW);
      digitalWrite(alim_millier,LOW);
      digitalWrite(alim_centaine,LOW);
      digitalWrite(alim_dizaine,LOW);
      digitalWrite(alim_unite,LOW);
    }

    void loop() {
      //fonction principale
      for(int i=0; i<10000; i++) {
        //boucle qui permet de compter de0 à9999(=10000 valeurs)
        afficher_nombre(i);//appelde la fonction affichage avec envoi du nombre à afficher
      }
    }

    //fonction permettant d'afficherun nombre sur quatre afficheurs
    void afficher_nombre(int nombre) {
      long temps;//variable utilisée poursavoir le temps écoulé
      int unite=0,dizaine=0,centaine=0, millier=0;//variable pour chaque afficheur
      millier=nombre/1000;//on récupère les milliers
      centaine=(nombre-1000*millier)/100;//on récupère les centaines
      dizaine=(nombre-(centaine*100)-(millier*1000))/10;//on récupère les dizaines
      unite=nombre-(millier*1000)-(centaine*100)-(dizaine*10);//on récupère les unités
      temps=millis();//on récupère le temps courant
      //tant qu'on a pas affiché ce chiffre pendant au moins 500 milliseconde
      //permet donc de pouvoir lire le nombre affiché
      while((millis()-temps)<500) {
        //on affiche le nombre
        //d'abord les milliers pendant 5ms
        digitalWrite(alim_millier,HIGH);
        afficher_CD(millier);//on appelle la fonction qui permet d'afficher le chiffre millier
        digitalWrite(alim_centaine,LOW);
        digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
        digitalWrite(alim_unite,LOW);//le transistor est bloqué
        delay(5);
        //d'abord les centaines pendant 5ms
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,HIGH);//le transistor de l'afficheur des centaines est saturé, donc l'afficheur est allumé
        afficher_CM(centaine);//on appelle la fonction qui permet d'afficher le chiffre centaine
        digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
        digitalWrite(alim_unite,LOW);//le transistor est bloqué
        delay(5);
        //ensuite les dizaines pendant 5 ms
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,LOW);// transistor est bloqué
        digitalWrite(alim_dizaine,HIGH);//transistor saturé
        afficher_CM(dizaine);
        digitalWrite(alim_unite,LOW);//transistor bloqué
        delay(5);
        //on affiche les unités 5 ms
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,LOW);//transistor bloqué
        digitalWrite(alim_dizaine,LOW);//transistor bloqué
        digitalWrite(alim_unite,HIGH);//transistor saturé
        afficher_UD(unite);
        delay(5);
      }
    }

    //fonction écrivant sur les premiers afficheurs
    void afficher_UD(int chiffre) {
      digitalWrite(bit_A,LOW);
      digitalWrite(bit_B,LOW);
      digitalWrite(bit_C,LOW);
      digitalWrite(bit_D,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_D,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_C,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_B,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_A,HIGH);
        chiffre=chiffre-1;
      }
    }

    //fonction écrivant sur le second afficheur
    void afficher_CM(int chiffre) {
      digitalWrite(bit_E,LOW);
      digitalWrite(bit_F,LOW);
      digitalWrite(bit_G,LOW);
      digitalWrite(bit_H,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_H,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_G,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_F,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_E,HIGH);
        chiffre=chiffre-1;
      }
    }

    void afficher_CD(int chiffre) {
      digitalWrite(bit_I,LOW);
      digitalWrite(bit_J,LOW);
      digitalWrite(bit_K,LOW);
      digitalWrite(bit_L,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_L,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_K,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_J,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_I,HIGH);
        chiffre=chiffre-1;
      }
    }

And here the code for 5 displays with "bugs" :

    //définition des broches du premier décodeur
    const int bit_A=8;
    const int bit_B=9;
    const int bit_C=10;
    const int bit_D=11;
    //définition du brochage du deuxieme decodeur
    const int bit_E=22;
    const int bit_F=24;
    const int bit_G=26;
    const int bit_H=28;
    //définition du brochage du 3ième décodeur
    const int bit_I=40;
    const int bit_J=42;
    const int bit_K=44;
    const int bit_L=46;
    //définition des broches des transistors
    const int alim_dm= 3;
    const int alim_millier=4;
    const int alim_centaine=5;
    const int alim_dizaine=6;
    const int alim_unite=7;
    void setup() {
      //les broches sont toutes des sorties
      pinMode(bit_A,OUTPUT);
      pinMode(bit_B,OUTPUT);
      pinMode(bit_C,OUTPUT);
      pinMode(bit_D,OUTPUT);
      pinMode(bit_E,OUTPUT);
      pinMode(bit_F,OUTPUT);
      pinMode(bit_G,OUTPUT);
      pinMode(bit_H,OUTPUT);
      pinMode(bit_I,OUTPUT);
      pinMode(bit_J,OUTPUT);
      pinMode(bit_K,OUTPUT);
      pinMode(bit_L,OUTPUT);
      pinMode(alim_dm,OUTPUT);
      pinMode(alim_millier,OUTPUT);
      pinMode(alim_centaine,OUTPUT);
      pinMode(alim_dizaine,OUTPUT);
      pinMode(alim_unite,OUTPUT);
      //les broches sont toutes mises à l'état bas
      digitalWrite(bit_A,LOW);
      digitalWrite(bit_B,LOW);
      digitalWrite(bit_C,LOW);
      digitalWrite(bit_D,LOW);
      digitalWrite(bit_E,LOW);
      digitalWrite(bit_F,LOW);
      digitalWrite(bit_G,LOW);
      digitalWrite(bit_H,LOW);
      digitalWrite(bit_I,LOW);
      digitalWrite(bit_J,LOW);
      digitalWrite(bit_K,LOW);
      digitalWrite(bit_L,LOW);
      digitalWrite(alim_dm,LOW);
      digitalWrite(alim_millier,LOW);
      digitalWrite(alim_centaine,LOW);
      digitalWrite(alim_dizaine,LOW);
      digitalWrite(alim_unite,LOW);
    }

    void loop() {
      //fonction principale
      for(int i=0;i<100000;i++)//boucle qui permet de compter de0 à 99999(=100000 valeurs) {
        afficher_nombre(i);//appelde la fonction affichage avec envoi du nombre à afficher
      }
    }

    //fonction permettant d'afficherun nombre sur quatre afficheurs
    void afficher_nombre(int nombre) {
      long temps;//variable utilisée poursavoir le temps écoulé
      int unite=0,dizaine=0,centaine=0, millier=0, dm=0;//variable pour chaque afficheur
      dm=nombre/10000;//on récupère les dm
      millier=(nombre-(10000*dm))/1000;//on récupère les milliers
      centaine=(nombre-1000*millier)-(10000+dm)/100;//on récupère les centaines
      dizaine=(nombre-(centaine*100)-(millier*1000)-(dm*10000))/10;//on récupère les dizaines
      unite=nombre-(dm*10000)-(millier*1000)-(centaine*100)-(dizaine*10);//on récupère les unités

      temps=millis();//on récupère le temps courant
      //tant qu'on a pas affiché ce chiffre pendant au moins 500 milliseconde
      //permet donc de pouvoir lire le nombre affiché
      while((millis()-temps)<500) {
        //on affiche le nombre
        //d'abord les dms pendant 5ms
        digitalWrite(alim_dm,HIGH);
        afficher_CD(dm);//on appelle la fonction qui permet d'afficher le chiffre dm
        digitalWrite(alim_millier,LOW);//le transistor bloqué
        digitalWrite(alim_centaine,LOW);//le transistor est bloqué
        digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
        digitalWrite(alim_unite,LOW);//le transistor bloqué
        delay(10);
        //d'abord les millier pendant 5ms
        digitalWrite(alim_dm,LOW);
        digitalWrite(alim_millier,HIGH);//le transistor de l'afficheur des centaines est saturé, donc l'afficheur est allumé
        afficher_CM(millier);//on appelle la fonction qui permet d'afficher le chiffre centaine
        digitalWrite(alim_centaine,LOW);//le transistor est bloqué
        digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
        digitalWrite(alim_unite,LOW);//le transistor bloqué
        delay(10);
        //ensuite les centaine pendant 5 ms
        digitalWrite(alim_dm,LOW);
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,HIGH);// transistor est bloqué
        afficher_CM(centaine);
        digitalWrite(alim_dizaine,LOW);//transistor saturé
        digitalWrite(alim_unite,LOW);//transistor bloqué
        delay(10);
        //on affiche les dizaines 5 ms
        digitalWrite(alim_dm,LOW);
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,LOW);//transistor bloqué
        digitalWrite(alim_dizaine,HIGH);//transistor bloqué
        afficher_UD(dizaine);
        digitalWrite(alim_unite,LOW);//transistor saturé
        delay(10);
        //on affiche les unités
        digitalWrite(alim_dm,LOW);
        digitalWrite(alim_millier,LOW);
        digitalWrite(alim_centaine,LOW);//transistor bloqué
        digitalWrite(alim_dizaine,LOW);//transistor bloqué
        digitalWrite(alim_unite,HIGH);//transistor saturé
        afficher_UD(unite);
        delay(10);
      }
    }

    //fonction écrivant sur les premiers afficheurs
    void afficher_UD(int chiffre) {
      digitalWrite(bit_A,LOW);
      digitalWrite(bit_B,LOW);
      digitalWrite(bit_C,LOW);
      digitalWrite(bit_D,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_D,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_C,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_B,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_A,HIGH);
        chiffre=chiffre-1;
      }
    }

    //fonction écrivant sur le second afficheur
    void afficher_CM(int chiffre) {
      digitalWrite(bit_E,LOW);
      digitalWrite(bit_F,LOW);
      digitalWrite(bit_G,LOW);
      digitalWrite(bit_H,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_H,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_G,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_F,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_E,HIGH);
        chiffre=chiffre-1;
      }
    }

    void afficher_CD(int chiffre) {
      digitalWrite(bit_I,LOW);
      digitalWrite(bit_J,LOW);
      digitalWrite(bit_K,LOW);
      digitalWrite(bit_L,LOW);
      if(chiffre>=8) {
        digitalWrite(bit_L,HIGH);
        chiffre=chiffre-8;
      }
      if(chiffre>=4) {
        digitalWrite(bit_K,HIGH);
        chiffre=chiffre-4;
      }
      if(chiffre>=2) {
        digitalWrite(bit_J,HIGH);
        chiffre=chiffre-2;
      }
      if(chiffre>=1) {
        digitalWrite(bit_I,HIGH);
        chiffre=chiffre-1;
      }
    }
    //Fin du programme

I've been trying for weeks to understand the problem. All displays work fine, and if I adapt the code for 4 displays and try to use any 4 of the 6 displays it works fine (I have tried a combination such as displays: 1, 2, 3, 4 or 2, 3, 4, 5 or 3, 4, 5, 6 or 1, 2, 5, 6, everything works).

Thanks to a conversation on [the Arduino forum][3], I also tried this code for 5 displays but I still have the same problem:

    //Da
    const int bit_A=8;
    const int bit_B=9;
    const int bit_C=10;
    const int bit_D=11;
    //Db
    const int bit_E=22;
    const int bit_F=24;
    const int bit_G=26;
    const int bit_H=28;
    //Dc
    const int bit_I=40;
    const int bit_J=42;
    const int bit_K=44;
    const int bit_L=46;
    // transistors
    const int alim_dizainemillier= 3;
    const int alim_millier=4;
    const int alim_centaine=5;
    const int alim_dizaine=6;
    const int alim_unite=7;
    void setup() {
      pinMode(bit_A,OUTPUT);
      pinMode(bit_B,OUTPUT);
      pinMode(bit_C,OUTPUT);
      pinMode(bit_D,OUTPUT);
      pinMode(bit_E,OUTPUT);
      pinMode(bit_F,OUTPUT);
      pinMode(bit_G,OUTPUT);
      pinMode(bit_H,OUTPUT);
      pinMode(bit_I,OUTPUT);
      pinMode(bit_J,OUTPUT);
      pinMode(bit_K,OUTPUT);
      pinMode(bit_L,OUTPUT);
      pinMode(alim_dizainemillier,OUTPUT);
      pinMode(alim_millier,OUTPUT);
      pinMode(alim_centaine,OUTPUT);
      pinMode(alim_dizaine,OUTPUT);
      pinMode(alim_unite,OUTPUT);
      digitalWrite(bit_A,LOW);
      digitalWrite(bit_B,LOW);
      digitalWrite(bit_C,LOW);
      digitalWrite(bit_D,LOW);
      digitalWrite(bit_E,LOW);
      digitalWrite(bit_F,LOW);
      digitalWrite(bit_G,LOW);
      digitalWrite(bit_H,LOW);
      digitalWrite(bit_I,LOW);
      digitalWrite(bit_J,LOW);
      digitalWrite(bit_K,LOW);
      digitalWrite(bit_L,LOW);
      digitalWrite(alim_dizainemillier,LOW);
      digitalWrite(alim_millier,LOW);
      digitalWrite(alim_centaine,LOW);
      digitalWrite(alim_dizaine,LOW);
      digitalWrite(alim_unite,LOW);
    }

    void loop() {
      for(int i=0;i<100000;i++) {
        afficher_nombre(i);
        delay(5);
      }
    }

    void afficher_nombre(int nombre) {
      long temps;
      int unite=0,dizaine=0,centaine=0, millier=0, dizainemillier=0;
      dizainemillier=nombre/10000;
      millier=(nombre-(10000*dizainemillier))/1000;
      centaine=(nombre-(1000*millier)-(10000*dizainemillier))/100;
      dizaine=(nombre-(centaine*100)-(millier*1000)-(dizainemillier*10000))/10;
      unite=nombre-(dizainemillier*10000)-(millier*1000)-(centaine*100)-(dizaine*10);
      temps=millis();
      while((millis()-temps)<500){
        afficher_CD(dizainemillier);
        digitalWrite(alim_dizainemillier, HIGH);
        delay(5);
        digitalWrite(alim_dizainemillier, LOW);
        afficher_CM(millier);
        digitalWrite(alim_millier, HIGH);
        delay(5);
        digitalWrite(alim_millier, LOW);
        afficher_CM(centaine);
        digitalWrite(alim_centaine, HIGH);
        delay(5);
        digitalWrite(alim_centaine, LOW);
        afficher_UD(dizaine);
        digitalWrite(alim_dizaine, HIGH);
        delay(5);
        digitalWrite(alim_dizaine, LOW);
        afficher_UD(unite);
        digitalWrite(alim_unite, HIGH);
        delay(5);
        digitalWrite(alim_unite, LOW);
      }
    }

    void afficher_UD(int chiffre) {
      digitalWrite(bit_A,chiffre & 1);
      digitalWrite(bit_B,chiffre & 2);
      digitalWrite(bit_C,chiffre & 4);
      digitalWrite(bit_D,chiffre & 8);
    }

    void afficher_CM(int chiffre) {
      digitalWrite(bit_E,chiffre & 1);
      digitalWrite(bit_F,chiffre & 2);
      digitalWrite(bit_G,chiffre & 4);
      digitalWrite(bit_H,chiffre & 8);
    }

    void afficher_CD(int chiffre) {
      digitalWrite(bit_I,chiffre & 1);
      digitalWrite(bit_J,chiffre & 2);
      digitalWrite(bit_K,chiffre & 4);
      digitalWrite(bit_L,chiffre & 8);
    }

Any clue is very welcome! Thanks!

  [1]: https://youtu.be/cTKuFk76ZP0
  [2]: https://youtu.be/boCAtVDET5w
  [3]: https://forum.arduino.cc/index.php?topic=475902.msg3261509#msg3261509

body:
I think it's because I use `int` and I should use `long` to avoid overflow... for the number I want to display:

    void loop()
    {
     for(int i=0;i<100000;i++)
     {
       afficher_nombre(i);
       delay(5);
     }
    }

should be :

    void loop()
    {
     for(long i=0;i<100000;i++)
     {
       afficher_nombre(i);
       delay(5);
     }
    }

 And also a parentheses problem solved thanks to cattledog on [this forum][1]

  [1]: https://forum.arduino.cc/index.php?topic=475902.15


body:
> Here is the code that works fine for 4 displays:

both code pieces suffer from the use of "delay()".

here is what I used - https://dannyelectronics.wordpress.com/2017/06/30/a-more-flexible-driver-for-7-segment-leds/

it is written so the leds can be driven by individual pins so porting to  arduino requires no change to the source code - just a few macros to remap the IO operations.

also running it from a timer isr is the (only) way to go.

edit: here is to show how the code above gets to work here. I expanded it to cover 8 digits but only the first 6 digits effective. three macros are all it takes to repurpose it for arduino.

displaying a fixed "123456".

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

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

all the user code does is to dump the content to be displayed into the display buffer and the display routine, led_display() takes care of the rest.


message:
Why can't I define the constant A0 (some pin) to something?

What I'm doing wrong or why is it not working:

    #define Uin A0;

    void setup() {
    }

    void loop() {
      analogRead(Uin);
    }

Results in a `Error (expected ')' before ; token.`

I thought `#define` just exists as a place holder.

body:
Because you have a `;` at the end of your #define.

    #define Uin A0;
    analogRead(Uin);

becomes:

    analogRead(A0;);

The Arduino website mentions this in [their reference](https://www.arduino.cc/en/Reference/Define). For more in-depth detail about the C pre-processor you can read the (rather large) manual [here](https://gcc.gnu.org/onlinedocs/cpp/).


message:
How to code multiple conditions inside if statement?

I have a system that checks the value of a moisture sensor and will also check the time

    if (t.hour == 7 && t.min == 00 && moistureOneSensorValue >= 700) {
      RelayOne();
      RelayTwo();
    }

When `moistureOneSensorValue` is greater than or equal to 700 it means the soil is `DRY`, so when all conditions inside the if statement are true the `relayOne` and `relayTwo` functions will be called.

My problem is that when `moistureOneSensorValue` is still `moist` the above if statement will result in `false` and the `relayOne` and `relayTwo` functions will not be called. I want Arduino to execute and call the `relayOne` and `relayTwo` functions and disregard the `time`. I use time so that the system will only call the `relayOne` and `relayTwo` functions in the morning at exactly 7 AM every day, but it needs to check/make sure that the soil is `DRY`...

**Example**

First thing in the morning the system will check the time and sensor value; if the `if statement` results in `false` the system will keep monitoring and try the if statement until the soil is `DRY`. But I think when that happens it will be over 7 AM.

Sorry for the messy explanation.

body:
If the event is to be time independent then it follows you can not check the time.  If the event is to be both time independent and dependent then you need to add the code to handle the logic.

Consider checking if it is between 7am and, say, 7pm.  If true then test if the moisture detector is dry.  If true then close (watering) relays.

*(This is only a code example and has not been tested.)*

    if(t.hour >= 7 && t.hour <= 19)
    {
      while(moistureOneSensorValue >= 700)
      {
       RelayOne();
       RelayTwo();
      }
    }

Consider adding a state machine to mitigate possible problems by monitoring minimum times between events and maximum times of events.  For example, do not water more than once per 5 minutes.  Do not water more than 30 seconds at a time.  Do not water more then a total of 1 minute per hour.  Do not water more than 5 minutes per 24 hours.


body:
I'm not sure how quickly you soil could get dry, but I suspect what you want to do is to periodically check the dryness throughout the day. Say like every two hours:

    // Check every 2 hrs (when hr is even)
    if ( t.hour % 2 == 0 && moistureOneSensorValue >= 700 ) {...}

You could also bound it to only during the day time:

    if ( t.hour >= 7 // after 7a
      && t.hour <= 19 // before 7p
      && t.hour % 2 == 1 // every 2 hrs (when hr is odd)
      && moistureOneSensorValue >= 700 // soil is dry
    ) {...}


message:
NRF24L01+ Issues antenna

I have 2x NRF24L01+ communicating but they are unreliable. It doesn't matter if they are right night to each other or 100ft away. For some odd reason when I place my hand on the antenna it work perfectly. Why would this be?
I have one set up to send and one to receive. All I am sending from one to the other is a 3 digit number to turn on a relay.

body:
I found a solution. As the signals where too close I found where I could tone down the signal strength using:

       radio.setPALevel(RF24_PA_MIN);

Because I didn't want to loose long range capabilities too I send my packet out 4 times at this lower signal and then increase the strength back to max to send out another 4 packets. This way my close range and far range relay will receive the signal.


message:
How to make 4 digits 7 segments common cathode thermometer

I'm new to Arduino and I have this problem: The common cathode 4 digits 7-segments keep on blinking even the code and my connection is correct (in my opition). I have used an LM35 IC to read the temperature
 I've just followed this pattern:[![enter image description here][1]][1]
and I used this code:

    const int digitPins[4] = {5,4,3,2}; //4 common CATHODE pins of the display (inverted the pins order)
    const int clockPin = 7;    //74HC595 Pin 11
    const int latchPin = 8;    //74HC595 Pin 12
    const int dataPin = 12;     //74HC595 Pin 14
    const int tempPin = A0;     //temperature sensor pin
    const byte digit[10] =      //seven segment digits in bits
    {
      B00111111, //0
      B00000110, //1
      B01011011, //2
      B01001111, //3
      B01100110, //4
      B01101101, //5
      B01111101, //6
      B00000111, //7
      B01111111, //8
      B01101111  //9
    };
    int digitBuffer[4] = {0};
    int digitScan = 0;
    float tempC; //Deleted kelvin and farenheit

    void setup(){
      for(int i=0;i<4;i++)
      {
        pinMode(digitPins[i],OUTPUT);
      }
      pinMode(tempPin, INPUT);
      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);
      pinMode(tempPin, INPUT);
      //Serial.begin(9600);
    }

    //writes the temperature on display
    void updateDisp(){

      for(byte j=0; j<4; j++) {digitalWrite(digitPins[j], HIGH);} // Turns the display off. Changed to HIGH
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, MSBFIRST, B00000000);
      digitalWrite(latchPin, HIGH);

      delayMicroseconds(2);

      digitalWrite(digitPins[digitScan], LOW); //Changed to LOW for turning the leds on.

      digitalWrite(latchPin, LOW);
      if(digitScan==2)
        shiftOut(dataPin, clockPin, MSBFIRST, (digit[digitBuffer[digitScan]] | B10000000)); //print the decimal point on the 3rd digit
      else
        shiftOut(dataPin, clockPin, MSBFIRST, digit[digitBuffer[digitScan]]);

      digitalWrite(latchPin, HIGH);

      digitScan++;
      if(digitScan>3) digitScan=0;
    }

    void loop(){
      tempC = analogRead(tempPin)*0.00488;  //multiplied for this conversion constant
      tempC = tempC*10000;
      digitBuffer[3] = int(tempC)/1000;
      digitBuffer[2] = (int(tempC)00)/100;
      digitBuffer[1] = (int(tempC)0)/10;
      digitBuffer[0] = (int(tempC)0);

      if (digitBuffer[0]>=5) {
        digitBuffer[0] = 5;
      }
      else {
        digitBuffer[0] = 0;
      }

      delay(5);
      updateDisp();
    }

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

body:
First thing to check is that you have the IC and the 7-segment display module connected the correct way around. As a reference, the green wire is attached to Pin 14 of the 74HC595 IC, so pin 1 would be the top right pin. The 7-segment display should have the the dot points towards the bottom.

Check that you have a common cathode display. You can do this by applying a voltage, through a 220 ohm resistor, verifying that it lights up when positive is on pins A-G and Gnd connected to the common cathode pin.

Check the code by removing the temperature section of the code and just writing '0's to all 4 digits. In fact it would be worth testing the digits one by one. The below code should do just that (unverified):

<!-- language: c++ -->

    const int clockPin = 7;    //74HC595 Pin 11
    const int latchPin = 8;    //74HC595 Pin 12
    const int dataPin = 12;    //74HC595 Pin 14
    const int digitPins[4] = {5,4,3,2};

    void setup(){
      for(int i=0;i<4;i++)
      {
        pinMode(digitPins[i],OUTPUT);
        digitalWrite(digitPins[i], HIGH);
      }
      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);
    }

    void loop() {
      for(int i=0;i<4;i++)
      {
        //select the digit by enabling the common cathode (sink)
        digitalWrite(digitPins[i], LOW);

        // write '0'
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, MSBFIRST, 63);
        digitalWrite(latchPin, HIGH);
        delay(1000);
      }
    }

This code will display a '0' one digit at a time, each for 1 second.  If this code works then I suspect the problem lies in the `updateDisp()` function.

NB: In your code, tempPin is setup twice as an input.


message:
Multiple arduino Wireless communication

I would like to know what device and model to use for an application where I will have `1 arduino as a master` micro controller waiting to receive data from `5 slave arduino` microcontrollers.

The `Master` arduino will be connected to local network via Ethernet cable so once it receive data from a `Slave` controller it needs to post to server the information, get a response back and in case the response is a "true" value then the `Master` need to talk back to the `Slave` in order to turn a LED on.

There will be cases when maybe 3 of the `Slaves` will send data at the same time, this doesn't mean at exactly the same millisecond. So I don't know if there will be data lost.

I was reading that `Xbee` maybe is the best device because it has a feature that will hold the data until there is a success communication with slave.

> Is this a doable and "easy" task using `Xbee`? Anyone that already try to do something like this that can guide me?
>
>> I was reading that there is a device `nRF24l01` that is very cheap and can do exactly what I need. Just that I don't really know how to start.

Appreciate any advice or help.

body:
It really depends on the communication range and context required.

If your _slaves_ are within 10-20 meters from the _master_ device and the environment is not polluted (in terms of magnetic field) you can achieve good results with very inexpensive nRF24L01+ modules which operate in the 2.4GHz.

If you need to cover greater distances (in the order of 100 meters) or a polluted environment then you have to resort to shorter wavelengths or more powerful devices, but that brings in the question on how are you powering your _slaves_: on battery power those ranges get pretty power hungry.

Generally speaking I would say this question should be rejected as it's going to start a debate rather than provide a solution.

You can get some introductions on how to use nRF24L01+ modules simply searching online:

 - [some posts on my blog][1]
 - [the Arduino library I always advice][2]
 - [a pretty valid guide][3]

  [1]: https://rlogiacco.wordpress.com/?s=nrf24
  [2]: https://github.com/nRF24/RF24
  [3]: https://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo


message:
Write array to serial port

The Code Below now works:

    void SendCTRL (String &input)
    {
      const char *hin = input.c_str();    // Get character array
      int clen = input.length()/2;
      unsigned char cmd[clen+1]; // Leave a byte for null terminator
      for (int i=0; i < 2*clen; i+=2)
      {
        cmd[i/2] = dehex(hin[i])<<4 | dehex(hin[i+1]);
      }
      cmd[clen] = 0;                     // Null-byte terminator
      digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
      for (int i=0; i< clen; i++)
      {
      RS485Serial.write(cmd[i]);   // Send string someplace
      //Serial.write(cmd[i]);
      }
      delay(clen/4);
      digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
      Serial.println();

    }

    byte dehex(char c)
    {
      // Get nibble value 0...15 from character c
      // Treat digit if c<'A', else letter
      return c<'A'? c & 0xF : 9 + (c & 0xF);
    }

    byte dehex(char c)
    {
      // Get nibble value 0...15 from character c
      // Treat digit if c<'A', else letter
      return c<'A'? c & 0xF : 9 + (c & 0xF);
    }

Input is a series of ASCII-encoded hex digits and getting the output to print the byte values of the hex.

body:
There's some logic slightly askew with your length calculations:

    int clen = input.length()/2;

Ok, so for a (say) 20 character string you have `clen=10`.

    for (int i=0; i < clen; i+=2)

Ok, so for the first 10 characters of your 20 character string you take alternate ones (0, 2, 4, 6, 8)

What about the last 10 characters?  `clen` is 10, not 20, since you divided it by 2 at the start.

Decide if you want clen to be half the string length, then count *double*, or is the whole string length, and you divide it by 2 where you want the final string length. Or have two variables - one before and one after dividing by 2.

Oh, and you should pass your String parameter *by reference* so you don't duplicate the object and end up fragmenting your heap.

    void SendCTRL (String &input)

I haven't gone into depth about the working of your `dehex` function, but this is the function I always use and works well:

    unsigned char h2d(char hex)
    {
        if(hex > 0x39) hex -= 7; // adjust for hex letters upper or lower case
        return(hex & 0xf);
    }

Also you should *or* your values together, not *add* them:

    cmd[i/2] = (dehex(hin[i])<<4) | dehex(hin[i+1]);

This would go some way to fixing your current issue, since `|` has a different precedence to `+`. At the moment you have effectively:

    cmd[i/2] = dehex(hin[i]) << (4 + dehex(hin[i+1]));

since the `+` happens before the `<<`, whereas what you want is:

    cmd[i/2] = (dehex(hin[i]) << 4) + dehex(hin[i+1]);

However with `|` instead you get

    cmd[i/2] = (dehex(hin[i]) << 4) | dehex(hin[i+1]);

because the `<<` happens before the `|`

Here is your code written in pure C to run on a PC (faster to debug and test than an Arduino when you're on Linux):

    #include <stdio.h>
    #include <string.h>

    unsigned char dehex(char c)
    {
      // Get nibble value 0...15 from character c
      // Treat digit if c<'A', else letter
      return c<'A'? c & 0xF : 9 + (c & 0xF);
    }

    void SendCTRL (const char *hin)
    {
      int ilen = strlen(hin);
      int clen = ilen / 2;
      unsigned char cmd[clen+1]; // Leave a byte for null terminator
      for (int i=0; i < ilen; i+=2)
      {
        cmd[i/2] = dehex(hin[i])<<4 | dehex(hin[i+1]);
        printf("x\n", cmd[i/2]);
      }
      cmd[clen] = 0;                     // Null-byte terminator
      for (int i = 0; i < clen; i++) {
        printf("%c", cmd[i]);
      }
    }

    void main() {
        SendCTRL("010307E40001C549");
    }


message:
Arduino Nano + (2* tlc5940) + 34 LEDs = Power Questions

This is an adapted layout for two tlc5940 hooked up to an Arduino nano. The [original project can be found here][1]. I am a little unsure about the capacitors and resistors as that project had it hooked up to a 5v wall plug.

My Design will be running a pattern of PWM, blinking and chasing lights. The two red lights are off of the TLC5940s circuits because reds need a different resistance. If i am wrong, please let me know as that would simplify things.
[![enter image description here][2]][2]

Also as is the way of the stack community, any other red flags you can point out would be greatly appreciated as i am new to this game.

  [1]: http://howtomechatronics.com/projects/diy-led-heart-photo-frame-arduino-project/
  [2]: https://i.stack.imgur.com/lrlK5.jpg

body:
As Ignacio has mentioned the TLC5940 is a *constant current* driver. The 2kΩ resistor sets the current for the LEDs regardless of the forward voltage (or colour) or the supply voltage.

Also as Gerben says, move the 0.1µF (100nF) capacitor close to the TLC5940 as you can. There should be one for each TLC5940 since they are *decoupling capacitors*.

You might like to increase the capacitance of the electrolytic too. The purpose of that capacitor is to provide a low impedance energy source to supply the circuit (batteries are actually quite high impedance by comparison). Since you have lots of LEDs being controlled by PWM the current draw will be fluctuating wildly all the time, and lots of energy over brief periods will be wanted.

Another thing to watch, mentioned again by Ignacio, is the supply voltage for the TLC5940 is 5.5V *absolute maximum*. I wouldn't go much above 5V. Depending on what your batteries actually are you may be better running from 3 of them (4.5V alkaline AA - Ni-MH would be ~3.6V, so 4 of them, giving 4.8V, would be better in that situation).

I would also question your use of the TLC5940. They are not the easiest chips to drive requiring quite a strange protocol. Personally I prefer the TLC59116 which is the I2C variant of the same chip. Much easier to control from an Arduino, and requiring just 2 pins. Not so easy for bread-boarding though as they're SMD only.


message:
how to drive 500W of leds

I am currently developing a project that needs 9 led stripes, each led stripe has 5 meters, 300 leds, it consumes 60W per stripe in a total of 540W...

This are the led stripes - 5M 12W/M 24V SMD 2835

This led stripes use a 24V power supply.

The thing is I want to drive them with an arduino and PWM. What would I need to do it. I was looking for something like CAT4101 but I never dealt with so much power before and I would like your advice.

Thanks

body:
The led strips will have their own current limiting / drivers. A couple of quick calculations:

* 24V at 12W is (I=P/V) 12/24 = 0.5A per meter
* 5 meters = 0.5*5 = 2.5A

So each strip takes 2.5A. The CAT4101 is a 1A max driver, but since it is a *constant current* driver it's not suitable for a strip that has its own current control built in.

I suspect each meter consists of 10 chains of 6 LEDs with a current limiting resistor or two. Out of interest, calculations:

* 6 LEDs at (say) 3V forward voltage would be 18V.
* 24 - 18 = 6 volts to drop
* 500mA divided by 10 chains = 50mA
* R=V/I = 6 / 0.05 = 120Ω current limiting resistors.
* P=I²R = 0.05²×6 = 300mW dissipated from the resistors.

Instead all you need is an N-channel MOSFET as a low-side switch that can operate with that much current and not dissipate too much heat while switching. The more you derate the MOSFET the less heatsinking it would need.

A quick look on Digikey gave a possible match of [PSMN022-30PL](https://www.digikey.com/product-detail/en/nexperia-usa-inc/PSMN022-30PL,127/1727-5893-ND/2606361) - 30V, 30A, 27mΩ (typ) at 4.5V gate voltage.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/KQHep.png)

<!-- End schematic -->


message:
float not a float

I am trying to read a SDM220 meter on my solar setup. I've been reading it using Modbus SCADA, so know it all works ok.
But I want to read it with my Arduino Mega 256. My problem is that when I run the code below the final value MtrKWh , is not float value. it's actual value is printed.
Here is a copy of the output.

17241 MtrKWh1 1129906176 MtrKWh1<<16 57737 MtrKWh2 1129963913 MtrKWh3 11299639.00 MtrKWh 2

the value '1129963913'       MtrKWh3,

if I turn it into Binary is
01000011010110011110000110001001,

if I convert this to binary using https://www.h-schmidt.net/FloatConverter/
it gives me the value

217.881,

the very value I expect. Am I missing some brackets somewhere?
So how do I get MtrKWh to print its float value?
I have left a lot of commented out bits to show the several things I have tried. Sorry if it appears messy, I will tidy it up once I solve this problem.
I'm sure it is something simple, but, I haven't been able to see it so far.
Any sugestions would be appreciated.

        // MtrV, MtrC, MtrW, MtrKWh
        //void AddressRegistry_0()
        result = sdm220_modbus.readInputRegisters(0x48, 2);
        //while (!result == 0) {
        // delay(10);
        // result = sdm220_modbus.readInputRegisters(0x156,4);
        //}
       if (result == sdm220_modbus.ku8MBSuccess)
       {
        // 1 Serial.println((node.getResponseBuffer(0x0D) + node.getResponseBuffer(0x0E) << 16)/100.0f);
        // 2 pvpower = ((long)node.getResponseBuffer(0x03) << 16 | node.getResponseBuffer(0x02)) / 100.0f;
        // 3 long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4;
        // 1 working ?? MtrKWh1 = (((long)sdm220_modbus.getResponseBuffer(0x0) + sdm220_modbus.getResponseBuffer(0x1) << 16)/6.f);
        // 2 working ?? MtrKWh1 = ((long)sdm220_modbus.getResponseBuffer(0x0) << 16 | sdm220_modbus.getResponseBuffer(0x1)) / 100.3f;
        // 3 working MtrKWh1 = (( sdm220_modbus.getResponseBuffer(0x0)  << 16) |  sdm220_modbus.getResponseBuffer(0x1))  / 16.3f;
        //
       // float MtrKWh0 =((float)(sdm220_modbus.getResponseBuffer( 0) << 16 | sdm220_modbus.getResponseBuffer( 1)));
        //      Serial.print(MtrKWh0);
        //    Serial.print(" MtrKWh0     ");

    signed long MtrKWh1 = sdm220_modbus.getResponseBuffer(0x0);
    Serial.print(" ");
    Serial.print(MtrKWh1);
    Serial.print(" MtrKWh1");

    MtrKWh1 = MtrKWh1 << 16;
    Serial.print(" ");
    Serial.print(MtrKWh1);
    Serial.print(" MtrKWh1<<16");

    word MtrKWh2 = sdm220_modbus.getResponseBuffer(0x1);
    Serial.print(" ");
    Serial.print(MtrKWh2);
    Serial.print(" MtrKWh2");

    signed long MtrKWh3 = MtrKWh1 | MtrKWh2;
    Serial.print(" ");
    Serial.print(MtrKWh3);
    Serial.print(" MtrKWh3");

    float (MtrKWh) = float (MtrKWh3) / 10000.0;
    Serial.print(" ");
    Serial.print(MtrKWh);
    Serial.print(" MtrKWh     ");

    //uint32_t x = 0x3f322e3f;
    //float y = *(float*)&x;
    //Serial.print (y, 6);
    // Serial.print(" MtrKWhxxx ");

       }
       else
       {
        rs485DataReceived = false;
        Serial.println("Fail sdm220_modbus.readInputRegisters(0x0, 1) ");
       }

body:
You need to convert the format by overlaying one type on top of the other, rather than casting from one type to another.

1000 as an integer cast to a floating point value is still 1000.

You have an example of how it can be done in comments:

    //float y = *(float*)&x;

However this method is called *type punning* and is frowned upon (there are compiler options that can prevent it being used).  Instead using a *union* is a better option:

    union ifloat {
        uint8_t bytes[4];
        float val;
    };

    void setup() {
        ifloat f;
        Serial.begin(115200);
        f.bytes[3] = 0x43;
        f.bytes[2] = 0x59;
        f.bytes[1] = 0xE1;
        f.bytes[0] = 0x89;
        Serial.println(f.val, 4);

    }

    void loop() {
    }

So you can get the byte order right your current numeric value of 1129963913 is 0x4359E189 in hexadecimal. Byte 3 is therefore the most significant byte and byte 0 the least significant. Note that it can change from system to system depending on the *endianness* of the chip.

How it works is quite simple. You have 4 bytes in memory, and the union just gives you different views of those 4 bytes.

You can either see them as four individual bytes (f.bytes[0-3]) or as a floating point value (f.val).

You can understand more about how the four bytes describe the floating point number by understanding more about the [IEEE 754 Single Precision Floating Point Format](https://en.wikipedia.org/wiki/Single-precision_floating-point_format).

----

You can achieve the same thing using `reinterpret_cast`, but that has to be done using *pointers*, not the values, which makes it a little more complex to understand:

    // Your incoming 32-bit value
    uint32_t l = 1129963913;

    // A pointer to the same memory with a different type
    float *f = reinterpret_cast<float *>(&l);

    // Print the *content* of the pointer interpreted as a float.
    Serial.println(*f, 3);