body:
I have a C program for the attiny85, that I want to disassemble and display with interleaved source code.

Here's my program:
test.c

    #include <avr/io.h>
    int main() {
        for(int i=0; i<100; i++) {
            PORTB=i;
        }
    }

Here's how I compile it: ```avr-gcc -g -O0 -mmcu=attiny85 -o test.elf test.c```

Finally, I generate the disassembly with interleaved source-code with the command: ```avr-objdump -S -D test.elf```

The disassembly of the text section shows the following disassembly **without interleaved source code**:

    00000030 <main>:
      30:   cf 93           push    r28
      32:   df 93           push    r29
      34:   00 d0           rcall   .+0             ; 0x36 <main+0x6>
      36:   cd b7           in      r28, 0x3d       ; 61
      38:   de b7           in      r29, 0x3e       ; 62
      3a:   1a 82           std     Y+2, r1 ; 0x02
      3c:   19 82           std     Y+1, r1 ; 0x01
      3e:   0a c0           rjmp    .+20            ; 0x54 <__SREG__+0x15>
      40:   88 e3           ldi     r24, 0x38       ; 56
      42:   90 e0           ldi     r25, 0x00       ; 0
      44:   29 81           ldd     r18, Y+1        ; 0x01
      46:   fc 01           movw    r30, r24
      48:   20 83           st      Z, r18
      4a:   89 81           ldd     r24, Y+1        ; 0x01
      4c:   9a 81           ldd     r25, Y+2        ; 0x02
      4e:   01 96           adiw    r24, 0x01       ; 1
      50:   9a 83           std     Y+2, r25        ; 0x02
      52:   89 83           std     Y+1, r24        ; 0x01
      54:   89 81           ldd     r24, Y+1        ; 0x01
      56:   9a 81           ldd     r25, Y+2        ; 0x02
      58:   84 36           cpi     r24, 0x64       ; 100
      5a:   91 05           cpc     r25, r1
      5c:   8c f3           brlt    .-30            ; 0x40 <__SREG__+0x1>
      5e:   80 e0           ldi     r24, 0x00       ; 0
      60:   90 e0           ldi     r25, 0x00       ; 0
      62:   0f 90           pop     r0
      64:   0f 90           pop     r0
      66:   df 91           pop     r29
      68:   cf 91           pop     r28
      6a:   08 95           ret

The disassembly makes somewhat sense, only that I miss the interleaved source code.

Interestingly enough, the output also includes a stab section, where I also find the main segment disassembled:

    #include <avr/io.h>

    int main() {
      30:   20 00           .word   0x0020  ; ????
      32:   00 00           nop
      34:   80 00           .word   0x0080  ; ????
      36:   00 00           nop
      38:   00 00           nop
        for(int i=0; i<100; i++) {
      3a:   00 00           nop
      3c:   40 00           .word   0x0040  ; ????
      3e:   00 00           nop
            PORTB=i;
      40:   80 00           .word   0x0080  ; ????
      42:   00 00           nop
      44:   00 00           nop
      46:   00 00           nop
      48:   5a 00           .word   0x005a  ; ????
        for(int i=0; i<100; i++) {
      4a:   00 00           nop
      4c:   80 00           .word   0x0080  ; ????
      4e:   00 00           nop
      50:   00 00           nop
      52:   00 00           nop
      54:   91 00           .word   0x0091  ; ????
      56:   00 00           nop
      58:   80 00           .word   0x0080  ; ????
      5a:   00 00           nop
      5c:   00 00           nop
      5e:   00 00           nop
      60:   b7 00           .word   0x00b7  ; ????
        }

    }

Now the output **includes source code, but the disassembly is wrong**.

How do I get an output were both is correct: the disassembled instructions and the interleaved source-code?

(avr-gcc (GCC) 9.3.0. https://arduino.stackexchange.com/questions/18429/interleave-assembly-and-source-for-avr-objdump does not seem to have the problem, although he's using the same compiler flags...)

title: Interleave disassembly + source with avr-objdump

Answers: 1

body:
The .stabs section contains debugging info, not actual code. There is no
point in trying to “disassemble” it. The `-D` option of avr-objdump
means “disassemble everything, whether or not you believe it's machine
code”. Not what you want. For your purpose, `-S` should be enough.

I do not know why your `main()` is displayed without source code. I
tried your exact same program with the exact same commands and I do see
the source interleaved with the assembly. I am using avr-gcc 5.4.0 and
avr-objdump 2.26.20160125 as shipped on Ubuntu Eoan.


body:
My `read` function returns an array of strings. i.e ssid and password

    String* configuration::read() {
        String rw_ssid = "";
        String rw_pswd = "";
        const int keys = 2;
        String read_ssid_pswd [keys];
        if (EEPROM.read(0) != 0) {

          for (int i = 0; i < 32; ++i) {
            rw_ssid += char(EEPROM.read(i));
          }
          for (int i = 32; i < 96; ++i) {
            rw_pswd += char(EEPROM.read(i));
          }
          Serial.print("rPASSWORD: ");
          Serial.println(rw_pswd);
          read_ssid_pswd[0] = rw_ssid;
          read_ssid_pswd[1] = rw_pswd;
          Serial.print("Sending ssid:");
          Serial.print(read_ssid_pswd[0]);
          Serial.print(" Pswd: ");
          Serial.println(read_ssid_pswd[1]);
          return read_ssid_pswd;
        } else {
          Serial.println("Data wifi not found!");
          return read_ssid_pswd;
        }
    }

I can see the print in the serial monitor.

    Sending ssid:SSID Pswd: password

but where this function is called from I have set it up like this:

    void setup() {
      Serial.begin(115200);
      Eeprom::configuration::initialize();
      String* ssid_password = Eeprom::configuration::read();
      Serial.print(">SSID: ");
      Serial.println(ssid_password[0]);
      Serial.print(">Password: ");
      Serial.println(ssid_password[1]);
      Funcs::connection::connectWifi(ssid_password[0], ssid_password[1]);
    }

and I get thing in the prints  I thought its not giving any error at compile time so it should be correct.

title: Nothing received from function returning array of strings

Answers: 2

body:
You can't return locally defined arrays like that. The array only exists in the function, and all you do is return a pointer to where that array was. As the array has gone when you leave the function your pointer just points to garbage.

Instead you should pass an array to the function that the function then populates.

body:
Majenko has it right, your String array should be allocated in Setup().  Notice that I passed back the success/failure of your initial EEPROM test as the return value.

    void setup() {
      Serial.begin(115200);
      Eeprom::configuration::initialize();
      const int keys = 2;
      String ssid_password[keys];
      if (Eeprom::configuration::read(ssid_password)) {
        Serial.print(">SSID: ");
        Serial.println(ssid_password[0]);
        Serial.print(">Password: ");
        Serial.println(ssid_password[1]);
        Funcs::connection::connectWifi(ssid_password[0], ssid_password[1]);
      } else {
        Serial.println("Data wifi was not found!");
      }
    }

The String array is the parameter, not the return value.  It is passed by reference.  The copying of EEPROM chars to String doesn't need to be into temporary variables, in fact it's inefficient and pointless; it can go straight into read_ssid_pswd[0] and [1], but I didn't want to change your code excessively, and delete the debugging serial writes.

    bool configuration::read(String read_ssid_pswd[]) {
        String rw_ssid = "";
        String rw_pswd = "";
        if (EEPROM.read(0) != 0) {

          for (int i = 0; i < 32; ++i) {
            rw_ssid += char(EEPROM.read(i));
          }
          for (int i = 32; i < 96; ++i) {
            rw_pswd += char(EEPROM.read(i));
          }
          Serial.print("rSSID: ");
          Serial.println(rw_ssid);
          Serial.print("rPASSWORD: ");
          Serial.println(rw_pswd);

          read_ssid_pswd[0] = rw_ssid;
          read_ssid_pswd[1] = rw_pswd;
          Serial.print("Sending ssid:");
          Serial.print(read_ssid_pswd[0]);
          Serial.print(" Pswd: ");
          Serial.println(read_ssid_pswd[1]);
          return true;
        } else {
          Serial.println("Data wifi not found!");
          return false;
        }
    }


body:
I am currently working on a project and want to transmit the information from a distance sensor from one arduino the another, but what i receive in the master board are not the correct measurements.

***Slave Code***

    #include <Wire.h>

    const int trig = 12;
    const int echo = 13;

    int state = 0;
    int count = 0;
    int contor = 0;
    int set_distance = 5;
    long duration, Distanceincm;

    void setup()
    {
      Wire.begin(4);                // join i2c bus with address #4
      Wire.onReceive(receiveEvent); // register event
      pinMode(trig, OUTPUT);
      pinMode(echo, INPUT);
      Serial.begin(9600);           // start serial for output
    }

    void loop()
    {
     digitalWrite(trig, HIGH);
      delay(15);
      digitalWrite(trig, LOW);
      duration = pulseIn(echo, HIGH);
      Distanceincm = (duration / 58);
      if (state == 0 && (Distanceincm < set_distance) ) {
        state = 1;
        count++;
        contor++;
        Serial.print("Distance=");
        Serial.println(Distanceincm);
        Serial.print("Count=");
        Serial.println(count);
        Serial.print("ConuntDay=");
        Serial.println(contor);
      }
      if (Distanceincm > set_distance) {
        state = 0;
      }
      delay(100);
    }

    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany)
    {
      while(1 < Wire.available()) // loop through all but the last
      {

      Wire.write(Distanceincm);
      Wire.write(count);
      Wire.write(contor);
    }

***Master Code***

    #include <Wire.h>

    void setup()
    {
      Wire.begin();        // join i2c bus (address optional for master)
      Serial.begin(9600);  // start Serial for output
    }

    void loop()
    {
      Wire.requestFrom(2, 6);    // request 6 bytes from slave device #2
      while(Wire.available())    // slave may send less than requested
      {
        long a = Wire.read();
        Serial.print ("Distance = ");
        Serial.println(a);

        int b = Wire.read();
        Serial.print ("Count = ");
        Serial.println(b);

        int c = Wire.read();
        Serial.print ("CountDay = ");
        Serial.println(c);
      }

      delay(500);
    }

What i get on the serial monitor is this :
[![enter image description here][1]][1]

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

title: Master Reader/Slave Sender with Distance Sensor

Answers: 1

body:
Your code has some flaws, that I will address here:

- The main problem, that you see here, is that you only let the slave write data into the buffer, when it is receiving data. But you never send data to it. So there is never anything in the buffer.

    In the slave code you have

        void receiveEvent(int howMany)
        {
          while(1 < Wire.available()) // loop through all but the last
          {

          Wire.write(Distanceincm);
          Wire.write(count);
          Wire.write(contor);
        }

    Besides the unbalanced parentheses (which let's me think, that this might not be the actual code, that you are running currently), you are writing to the buffer only inside the `receiveEvent()`. That only get's called, when the master does a Master-Write transmission (via `Wire.beginTransmission()` and `Wire.endTransmission()`). In the master code you are only using `Wire.requestFrom()`. If you want to send back data on a request, you need to use the `onRequest` callback of the `Wire` library. You need to set the appropriate callback function:

        Wire.onRequest(onRequestEvent);

    And then write data inside that callback function:

        void onRequestEvent(){
            Wire.write(...)
        }

    I will explain how to write the values correctly in a different point below.

- In the `receiveEvent()` function you want to loop through all received bytes but the last. But you are not doing anything with the data. You aren't even reading it. As your code currently stands, this line does not make any sense.

- In your master code you are requesting data from the slave with the address `2`. Your slave code initiates the `Wire` library with the address `4`. From that point there should never be a successful I2C transmission, unless you have another slave on the bus with the address `2` (another point, where I suspect, that these codes are not exactly the ones used for the test).

- In the master code you are using

        while(Wire.available())

    because the slave might have send less data, than requested. You are testing, that the number of available bytes is not zero. But then you are reading 3 bytes without checking again, which means, when you received 2 byte, you still would try to read 3 bytes, which cannot give good results.

    The condition should be `Wire.available() >= 3`, to check, if at least 3 bytes are in the buffer, because you are reading 3 bytes from it. But also the loop does not make much sense to me. As you have a binary protocol here, how would you treat additional data (meaning excess data, send after the first valid data frame)? You want to receive 3 values per transmission and you are reading 3 values in one iteration of the loop. If there where more data in the buffer, you would be reading the next 3 bytes, throwing away the first 3 bytes. I don't think, that is what you want.

    Instead use the return value of `Wire.requestFrom()`, which is the number of received bytes. Use it to distinguish valid transmissions, from those, which are too short:

        uint8_t n = Wire.requestFrom(4, 3);
        if(n >= 3){ // at least 3 bytes where received
            uint8_t value1 = Wire.read();
            uint8_t value2 = Wire.read();
            uint8_t value3 = Wire.read();
        }

    Any transmission, that is too small, will get ignored. Excess data in too long messages will also be ignored. Note, that I used `uint8_t`, which is an unsigned integer with 8 bits (1 byte) here for simplicity of that points logic. More about your data types and their implications on your code below.

- For the to send datatypes on the slave you have `int` and `long`. `int` is a signed integer with 16 bits, `long` is a signed long integer with 32 bits. (I suspect you don't need a `long` for the distance, as ultrasonic sensors mostly reach only 3m, but that is up to you). In contrast the argument of `Wire.write()` is an `uint8_t`, which has only 8 bits. That call is used to put exactly 1 byte into the buffer, not more. When you are using

        Wire.write(Distanceincm);

    you are putting the least significant byte of `Distanceincm` into the buffer. The rest will just be thrown away (this happens at the cast from `long` to `uint8_t`). This works as long, as the value is between 0 and 127 (which is the upper part of the `int8_t` value range). With higher (or lower) values your received data will be garbage. Instead you need to write every byte of your data into the buffer:

        Wire.write(Distanceincm  & 0x000000FF);
        Wire.write((Distanceincm & 0x0000FF00) >> 8);
        Wire.write((Distanceincm & 0x00FF0000) >> 16);
        Wire.write((Distanceincm & 0xFF000000) >> 24);

    With bitwise ANDing (`&`) of the hexadecimal value `0x000000FF`, we are deleting all bits, beside the least significant byte (analog with `0x0000FF00` for the second least significant byte, and so on). Then we are shifting the corresponding byte to the position of the least significant byte (8 bits for the seconds least significant byte, 16 bits for the third least significant byte, and so on), which then gets used by `Wire.write()`. To better understand this, read about bitwise operators on the web.

    You have to send both integer values in a similar fashion (though they both have only 2 bytes instead of 4).

- Now that we are sending more bytes, we also need to receive and read all these bytes correctly. First we need to request the correct number of bytes. 4 bytes for the `long` value and 2 bytes for both `int` values --> 8 bytes. So you need to request 8 bytes:

        Wire.requestFrom(4, 8);

    Then you need to read these bytes into the corresponding variables:

        long distance = Wire.read()
                        | (Wire.read() << 8)
                        | (Wire.read() << 16)
                        | (Wire.read() << 24);

    We are using the bitwise OR (`|`) to put the bytes together, shifting every byte to its correct position in the `long` value. In a similar way you are putting together the 2 `int` values.


body:
I come from a .Net background, typically I would 'lock' operations on an integer when I have thread-safe requirements. I'm not sure that applies to my sketch here? Could I potentially bypass an increment from one of my interrupt pins?

In summary, I have 2 interrupt pins - I want to increment a count which (every 5 seconds) writes via serial and resets.

I'm doing this to, kind of, avoid writing serial from within an interrupt - since I've read it's strongly discouraged.

    #include <Controllino.h>

    const byte interruptPin0 = CONTROLLINO_IN0;
    const byte interruptPin1 = CONTROLLINO_IN1;
    int counter1 = 0;
    int counter2 = 0;
    unsigned long previousMillis = 0;
    unsigned long interval = 5000;
    int a = 60;
    char buffer[256];

    void setup()
    {
      pinMode(interruptPin0, INPUT_PULLUP);
      pinMode(interruptPin1, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(interruptPin0), pin1Fired, RISING);
      attachInterrupt(digitalPinToInterrupt(interruptPin1), pin2Fired, RISING);
      Serial.begin(9600);
    }

    void loop()
    {
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval) {
        previousMillis = currentMillis;
        sprintf(buffer,"A%d",counter1);
        Serial.println(buffer);
        sprintf(buffer,"D%d",counter2);
        Serial.println(buffer);
        counter1 = counter2 = 0;
      }
    }

    void pin1Fired()
    {
      counter1++;
    }

    void pin2Fired()
    {
      counter2++;
    }

title: Is my sketch 'thread safe'?

Answers: 1

body:
There is indeed a race condition in your code: if an interrupt fires
while you are reading one of the counters, you might read garbage. If it
fires between reading and resetting the counter, you loose one count.

The way to prevent the race is to block interrupts while the main thread
(everything that does not run in interrupt context) accesses the
counters. BTW, do not forget to make the counters `volatile`.

The portions of the code that run with interrupts disabled are called
“critical sections”, and you should keep them as short as possible in
order to limit the interrupt latency they introduce. Typically, within
those critical sections you do nothing more than access the shared
variables. Example:

```c++
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    noInterrupts();  // start of critical section
    int counter1Copy = counter1;
    counter1 = 0;
    interrupts();  // end of critical section
    Serial.print("A");
    Serial.println(counter1Copy);
    noInterrupts();  // start of critical section
    int counter2Copy = counter2;
    counter2 = 0;
    interrupts();  // end of critical section
    Serial.print("D");
    Serial.println(counter2Copy);
  }
}
```


body:
I'm trying to control a re used DC motor from a drill (3,6V) with a L298N and a Arduino. It's powered with a 5V - 60A power supply.

I tried to follow this step by step tutorial (https://www.youtube.com/watch?v=dyjo_ggEtVU) but the motor is not spinning..yet. I can ear a noise, it starts to spin a micron and then stops.

I though that it could be something wrong with the power supply but I connected the 4V battery from the drill and the same thing is happening. If I connect the motor directly to the battery it is spinning nicely...

I though then that it was a code issue but I tried a no load test and measured the voltage without the motor -> I've the 4V required voltage. When the motor is connected I have 300mV instead of 4V.

Do you know what could go wrong? Is the L298 dead? just got it a few hours ago...

Would be nice if you have any clue.

Many thanks.

// Commande moteur
    int enA = 9;
    int in1 = 8;
    int in2 = 7;

    void setup()
    {
      // Définition des sorties

      pinMode(enA, OUTPUT);
      pinMode(in1, OUTPUT);
      pinMode(in2, OUTPUT);

      //Sens de rotation du moteur

      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);

      //Vitesse de rotation du moteur

      analogWrite(enA, 200);

      //Delay

      delay(5000);

       //Arrêt du moteur

      digitalWrite(in1, LOW);
      digitalWrite(in2, LOW);
    }

    void loop() {
      // put your main code here, to run repeatedly:

    }

[![Wiring][1]][1]

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

title: 3,6V DC motor spinning with L298N and Arduino

Answers: 1

body:
The L239 is a terrible motor driver. It's the kind of motor driver Noah used to control The Ark.

It requires a power supply that is at least 2.5V more than the "logic input high" voltage, which is rated at 2.3V. That means an *absolute minimum* of 4.8V, which is borderline for the Arduino's 5V pin, especially if you are running off USB (which can drop as low as 4.75V and still be within specification) and *way* out when powered from the battery.  It's really designed for driving motors in the 12V+ range.

To drive a low voltage motor like yours you need to pick a more modern MOSFET based motor driver.


body:
I'm on Linux Manjaro. I plugged my Arduino Leonardo clone (that I know works correctly). And tried to flash a blank project on it:
(My IDE version is `1.8.12`)
```c
void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}
```
It gives me this error:
```c
Sketch uses 3410 bytes (11%) of program storage space. Maximum is 28672 bytes.
Global variables use 149 bytes (5%) of dynamic memory, leaving 2411 bytes for local variables. Maximum is 2560 bytes.
processing.app.debug.RunnerException
    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:152)
    at cc.arduino.UploaderUtils.upload(UploaderUtils.java:77)
    at processing.app.SketchController.upload(SketchController.java:732)
    at processing.app.SketchController.exportApplet(SketchController.java:703)
    at processing.app.Editor$UploadHandler.run(Editor.java:2047)
    at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: processing.app.SerialException: Error touching serial port '/dev/ttyACM1'.
    at processing.app.Serial.touchForCDCReset(Serial.java:107)
    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:136)
    ... 5 more
Caused by: jssc.SerialPortException: Port name - /dev/ttyACM1; Method name - openPort(); Exception type - Permission denied.
    at jssc.SerialPort.openPort(SerialPort.java:170)
    at processing.app.Serial.touchForCDCReset(Serial.java:101)
    ... 6 more
```

title: Blank project gives errors while uploading Arduino Leonardo on Linux Manjaro

Answers: 1

body:
Okay I found a way to do this.
Open Terminal and type:
```bash
ls -l /dev/ttyACM*
```
you will get something like:

`crw-rw---- 1 root dialout 188, 0 5 apr 23.01 ttyACM0`

The "0" at the end of ACM might be a different number, or multiple entries might be returned. The data we need is `dialout` (is the group owner of the file).

Now we just need to add our user to the group:
```bash
sudo usermod -a -G dialout <username>
```
So for me that would be:
```bash
sudo usermod -a -G dialout john
```

BUT it seems to work with `dialout` on ubuntu/debian based distros. I am on `Manjaro` and instead of `dialout` I had to use `uucp` (and in general on `Arch` based distros) so:
```bash
sudo usermod -a -G uucp john
```
 You will need to log out and log in again for this change to take effect.

This is the procedure to access the serial port from the Arduino Software (IDE) if you get an error

After this procedure, you should be able to proceed normally and upload the sketch to your board or use the Serial Monitor.

Although for me that wasn't over. After doing this the only error I got was Arduino IDe simply saying that it doesn't have permission to write to that port. So I had to start `Arduino IDE` by:
```bash
sudo arduino
```
in the terminal. After that everything works just fine.

I found help at those links:

* https://www.arduino.cc/en/Guide/Linux#toc6
* https://forum.manjaro.org/t/how-to-enable-putty-usb-serial-converter-access-without-sudo/82736


body:
Newbie here !! Im trying to display the output of my MLX90614 sensor on mcufriend tft display (with arduino UNO). But unable to do so. I can only see the TFT being lit to white color, text -> "Target" flashes on screen for millisecond and then again white lit screen.

 1. But I tried tft-lcd sample codes, which are working fine &
 2. I also tried mlx90614 (mlxtext code), which is also working fine.

But I combined the two codes so as to output it on TFT, which doesnt work. Hence I think this code might have some issue.
Im a beginner pls help!!

    #include <Adafruit_TFTLCD.h>
    #include <Adafruit_GFX.h>
    #include <TouchScreen.h>
    #include <Wire.h>
    #include <Adafruit_MLX90614.h>

    #define LCD_CS A3
    #define LCD_CD A2
    #define LCD_WR A1
    #define LCD_RD A0
    #define LCD_RESET A4

    #define BLACK   0x0000
    #define YELLOW  0xFFE0
    #define WHITE   0xFFFF

    Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
    Adafruit_MLX90614 mlx = Adafruit_MLX90614();

    boolean buttonEnabled = true;

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

      mlx.begin();
      tft.reset();
      uint16_t identifier = tft.readID();
      tft.begin(identifier);
      tft.setRotation(1);
      tft.fillScreen(WHITE);
      tft.drawRect(0,0,319,240,YELLOW);

    }

    void loop() {

      tft.setCursor(0,1);
      tft.setTextSize(2);
      tft.print("Target  ");
      tft.setTextColor(BLACK);
      tft.print(mlx.readObjectTempC());
      tft.print(" C");
      Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
      Serial.println();
      delay(500);

    }

title: Output of mlx90614 to mcufriend tft/lcd, not getting displayed

Answers: 0


body:
I have an adafruit Ultimate GPS unit, its working fine. I am reading the GPS stream, via the command line, and one of the details, is "Angle: 167.97"
I looked at [a page about GPS sentences][1], but I'm still confused. Angle, is the direction of wind, or rudder, or angle at altitude. In this case i would guess its either rudder (because I don't know what rudder it may be referring to) or wind angle. Its changing frequently, but the device is stationary in my shed.

My questions are: What is angle referring to? as in, is it wind or rudder?
And where is it referring to? obviously, its not getting that data from its present location, so is that data coming from a whether station or something?

pardon me if this is the wrong exchange to post in, Im not sure where to ask.

  [1]: http://aprs.gids.nl/nmea/

title: GPS stream question

Answers: 1

body:
It will be referring to the angle of travel. That is, if you're moving (say driving in a car) what direction that movement is in.

But since you aren't moving the angle is meaningless. Instead it's trying to work out a direction from the random noise of the slight changes in the calculated location.

Unless your shed is in a tornado and flying through the air then the angle is not something you need to care about. Ignore it.


body: I have a relay attached to an Arduino Uno which I want to control using my raspberry pi 3b. And yes I know it can be done by attaching the relay directly to Pi but I cannot do so. Don't ask me why. That is why I want to know whether it is possible to use Pi's output signal as input for the Arduino or not. I do not have spare parts so I don't want to experiment. If anyone knows about this, please tell me.

title: Is it possible to use Pi's output signal as Arduino's input signal?

Answers: 1

body:
This way is fine: the Pi is a 3.3V based board, so connecting one of the GPIO pin from the pi to an Arduino will not damage it. Furthermore, the 3.3V are sufficient to be considered as `HIGH` even on a 5v Arduino like the UNO.

The other way around: connecting the *output* of a 5V Arduino to the *input* of a pi, will very likely damage the raspberry Pi!

So beware of your Pinmode before doing such a connection!


body:
I have two Arduino Megas with HC-05 on Serial1 connected to a Raspberry Pi 3b+ via bluetooth, using the HC-05 and the RPi's built-in bluetooth, and python's `pySerialTransfer` library to make the connections.

For reasons I am still trying to root cause, the bluetooth connection gets severed a few times an hour. Ideally, I'd get hours to perhaps a day between severed connections; is this a realistic goal?

Over a course of a few days, my testing has shown:

 1. Mega#1 median connection duration is 10 minutes & 88 minute max duration; 25 bytes sent by RPi->Arduino, and by Arduino->RPi every 0.2sec
 2. Mega#2 median connection duration is 38 minutes & 153 minute max duration; 4 bytes sent by RPi->Arduino, and by Arduino->RPi every 0.2sec

During this testing, they're completely stationary within about 12" of each other, so range should not be an issue.

My RPi code detects a lost connection by virtue of failure to receive a message within 5 seconds, and attempts to reestablish the connection, and that is successful about 80% of the time.  I have a second-tier of lost-connection recovery - resetting the HC-05 via an Arduino-triggered MOSFET - if a message isn't received by the Arduino in ~20 seconds, that works in the remainder of the cases, so I'm ultimately able to systematically recover within a max of about 30 seconds.  However, this lost connection for ~10-30 seconds every 10-60 minutes causes a poor user experience for my remote controls.

The Python errors given for about 95% of the failures are a lack of a receipt of a heartbeat message from the Arduino to the RPi python; about 5% give a unspecific `[Errno 5] Input/output error` error.

While I'm running down multiple theories via day-long stability tests (longer byte transmissions are more error prone? there's some bug in my Arduino code causing crashes, so remove all logic except the send/receive code to test?), I've read a few posts about how finicky & fragile bluetooth can be, and so I'm curious for some thoughts about the general goal / attempt to get a longer-term (hours to a day or more) connection.

Have folks been able to achieve this with the HC-05 on Arduino?  Or is a dropped connection every 10-60 minutes just something one needs to deal with through robust code?  Thank you.

title: Long term stability of bluetooth connections

Answers: 2

body:
Bluetooth communication works with fixed time intervals that both communication partners have to agree during the advertising and connection phases. Such an agreement could be: "While connected, lets' meet every second. If one does not show up during 3 meetings, let's leave the connection state".

From this you can see that timing is a very important factor in bluetooth communication. So **both communication partners need a very accurate clock.** No two clocks have exactly the same speed, one is always lagging the other.

It could be that one or multiple of the clocks of your HC-05's do have too much clock drift, so the connection will be lost. Maximum clock deviation allowed for a bluetooth clock is ±40 ppm (i.e. ±40 parts-per-million!) over the entire temperature range.

You could check this theory with multiple HC-05s. If individual modules lead to individual connection lengths, then this could be your problem.

body:
I ultimately found a solution, but for the benefit of others, wanted to share the tests that also did not prove fruitful. **TL;DR**: Reducing message rate from Arduino's to RPi solved the problem.

My hypotheses to test:

1. Hypothesis: Faulty Arduino code written by myself. Test: Remove all logic except read / write.
2. Hypothesis: Something to do with message size. Test: Add an extra arbitrary 80 bytes to the Mega#1 message.
3. Hypothesis: Too many small messages for RPi to deal with. Test: Reduce message frequency.
4. Hypothesis: Timing problem or other HC-05 fault as suggested by @stefan-wyss. Test: Swap modules with a 3rd one.
5. Hypothesis: Faulty RPi python code written by myself. Test: Return to basic python test harness that does nothing except exchange bluetooth messages.

Hypotheses #1 & #2 led to no appreciable difference in failure rate or failure mode.

However, hypothesis #3 was the winner, with both Arduinos running for 12+ hours so far with no severed communications.  (So I did not bother to test #4 & #5).

Specifically, in the original "problem code", there were 20 messages sent every second (and 40 read attempts; I have "overclocked" the receiving in relation to the sending make sure buffers don't fill up due to slight variations in RPi vs. Arduino clocks):

 - 5 sends of 25 bytes by Mega#1 to RPi per second
 - 5 sends of 25 bytes by RPi to Mega#1 per second
 - 5 sends of 4 bytes by Mega#2 to RPi per second
 - 5 sends of 4 bytes by RPi to Mega#2 per second

Some of those didn't really need that frequency to achieve my design goals; so I changed to:

 - **1** send of 25 bytes by Mega#1 to RPi **every 2 seconds**
 - 5 sends of 25 bytes by RPi to Mega#1 per second
 - **1** send of 4 bytes by Mega#2 to RPi **every 2 seconds**
 - 5 sends of 4 bytes by RPi to Mega#2 per second

So now, instead of the RPi receiving 10x/second, it receives 1x/second.  (It's still *attempting* to read 10x per second on each of the two Arduinos to minimize latency, but most of those return no data received). The RPI still has to send 10x/second (5x to each of the two Arduinos).

This simple change fixed the problem. I have no insight as to why the RPi couldn't handle the faster rate of message receipt; some benchmarking on my Python code showed that processing of the received heartbeat messages was not a bottleneck. But the important part, at least for me & the project, is that the problem is solved.


body:
I am building mini Arduino quadcopter project. I am using USB host shield for joystick support and nrf24l01 to transmit the data. Unfortunately, I got wrong data transmitted at the receiver and tried many things but doesn't work. I hope you can help me to further my understanding. It is my own first arduino project and it means a lot for me to keep this momentum. Please, guide me. So, i am using maniac library for nrf24l01 https://github.com/maniacbug/RF24/archive/master.zip . USB host shield is use https://www.arduinolibraries.info/libraries/usb-host-shield-library-2-0 . Help me to find out how to get the value that i send instead of getting error value on serial monitor...

This is the serial monitor GettingStarted from tmrh library
```

Now sending 26291...ok...Failed, response timed out.

Now sending 27494...ok...Got response 27494, round-trip delay: 22

Now sending 28518...ok...Got response 28518, round-trip delay: 22

Now sending 29541...ok...Failed, response timed out.

Now sending 30742...ok...Failed, response timed out.

Now sending 31944...ok...Got response 31944, round-trip delay: 23

Now sending 32968...ok...Got response 32968, round-trip delay: 23

Now sending 33991...ok...Got response 33991, round-trip delay: 23

Now sending 35014...ok...Failed, response timed out.

Now sending 36215...ok...Got response 36215, round-trip delay: 23

Now sending 37239...ok...Got response 37239, round-trip delay: 23

Now sending 38262...ok...Got response 38262, round-trip delay: 23

Now sending 39285...ok...Failed, response timed out.

Now sending 40486...ok...Got response 40486, round-trip delay: 23

Now sending 41510...ok...Failed, response timed out.
```

This is the output I send from transmitter (Now, I'm using maniac library, because tmrh give irrelevant response and only a joystick response to this, pretty sure)
```
X: 128  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 128  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 128  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 0  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 0  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 0  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0
X: 0  Y: 32  Hat: 0  Twist: 128  Slider: 15  Buttons A: 128  Buttons B: 0

```

This is what I receive
```
Throttle: 0    Yaw: 127    Pitch: 127    Roll: 127    Aux1: 0    Aux2: 0
Throttle: 0    Yaw: 127    Pitch: 127    Roll: 127    Aux1: 0    Aux2: 0
Throttle: 0    Yaw: 127    Pitch: 127    Roll: 127    Aux1: 0    Aux2: 0
Throttle: 0    Yaw: 32    Pitch: 0    Roll: 128    Aux1: 15    Aux2: 128
Throttle: 0    Yaw: 32    Pitch: 0    Roll: 128    Aux1: 15    Aux2: 128
Throttle: 0    Yaw: 32    Pitch: 0    Roll: 128    Aux1: 15    Aux2: 128
Throttle: 0    Yaw: 32    Pitch: 0    Roll: 128    Aux1: 15    Aux2: 128
Throttle: 0    Yaw: 32    Pitch: 0    Roll: 128    Aux1: 15    Aux2: 128
```
Here is my transmitter coding
```
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#include "le3dp_rptparser.h"

RF24 radio(9, 8); // select  CSN  pin
const byte address[6] = "00001"; //IMPORTANT: The same as in the receiver

//byte throttle = 512;       // min: 0 | max: 1023 | center: 512
//byte yaw = 512;       // min: 0 | max: 1023 | center: 512
//byte pitch = 8;       // up: 0 | right-up: 1 | right: 2 | right-down: 3 | down: 4 | left-down: 5 | left: 6 | left-up: 7 | center: 8
//byte roll = 128;   // min: 0 | max: 255 | center: 128
//byte AUX1 = 0;    // min: 0 | max: 255
//byte AUX2 = 0;
//byte joyButtonsB = 0;

  byte throttle ;
  byte yaw ;
  byte pitch ;
  byte roll;
  byte AUX1;
  byte AUX2;
  byte joyButtonsB;

struct MyData {
  byte throttle;
  byte yaw;
  byte pitch;
  byte roll;
  byte AUX1;
  byte AUX2;
};

MyData data;

void resetData()
{
  //This are the start values of each channal
  // Throttle is 0 in order to stop the motors
  //127 is the middle value of the 10ADC.

  data.throttle = 0;
  data.yaw = 127;
  data.pitch = 127;
  data.roll = 127;
  data.AUX1 = 0;
  data.AUX2 = 0;
}

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif

USB                                             Usb;
USBHub                                          Hub(&Usb);
HIDUniversal                                    Hid(&Usb);
JoystickEvents                                  JoyEvents;
JoystickReportParser                            Joy(&JoyEvents);

void setup()
{
  //Start everything up
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();

//  radio.setPayloadSize(32);
  resetData();

  Serial.begin( 115200 );
#if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  Serial.println("Start");

  if (Usb.Init() == -1)
      Serial.println("OSC did not start.");

  delay( 200 );

  if (!Hid.SetReportParser(0, &Joy))
      ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1  );

}

void loop()
{
    //Print all the values into the serial monitor:
    Usb.Task();

  data.throttle = throttle;
  data.yaw      = yaw;
  data.pitch    = pitch;
  data.roll     = roll;
  data.AUX1     = AUX1;
  data.AUX2     = AUX2;
    radio.write(&data, sizeof(MyData));

    Serial.print("X: ");
    Serial.print(data.throttle);
    Serial.print("\t Y: ");
    Serial.print(data.yaw);
    Serial.print("\t Hat: ");
    Serial.print(data.pitch);
    Serial.print("\t Twist: ");
    Serial.print(data.roll);
    Serial.print("\t Slider: ");
    Serial.print(data.AUX1);
    Serial.print("\t Buttons A: ");
    Serial.print(data.AUX2);
    Serial.print("\t Buttons B: ");
    Serial.println(joyButtonsB);
}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt)
{
  //Put the values from the joystick in another variable:
  throttle = evt->x;
  yaw = evt->y;
  pitch = evt->hat;
  roll = evt->twist;
  AUX1 = evt->slider;
  AUX2 = evt->buttons_a;
  joyButtonsB = evt->buttons_b;
}
```

This is the receiver

```

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
const byte address[6] = "00001";

RF24 radio(9, 8);

struct MyData {
byte throttle; //We define each byte of data input, in this case just 6 channels
byte  yaw;
byte pitch;
byte roll;
byte AUX1;
byte AUX2;
};

MyData data;

void resetData()
{

data.throttle = 0;
data.yaw = 127;
data.pitch = 127;
data.roll = 127;
data.AUX1 = 0;
data.AUX2 = 0;

}

/**************************************************/

void setup()
{
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

/**************************************************/

unsigned long lastRecvTime = 0;

void recvData()
{
while ( radio.available() ) {
radio.read(&data, sizeof(MyData));
lastRecvTime = millis(); //here we receive the data
}
}

/**************************************************/

void loop()
{
recvData();
unsigned long now = millis();
//Here we check if we've lost signal, if we did we reset the values
if ( now - lastRecvTime > 1000 ) {
// Signal lost?
resetData();
}

Serial.print("Throttle: "); Serial.print(data.throttle);  Serial.print("    ");
Serial.print("Yaw: ");      Serial.print(data.yaw);       Serial.print("    ");
Serial.print("Pitch: ");    Serial.print(data.pitch);     Serial.print("    ");
Serial.print("Roll: ");     Serial.print(data.roll);      Serial.print("    ");
Serial.print("Aux1: ");     Serial.print(data.AUX1);      Serial.print("    ");
Serial.print("Aux2: ");     Serial.print(data.AUX2);      Serial.print("\n");

}

/**************************************************/

 ```

title: i build quadcopter using USB HOST SHIELD + NRF24L01 but the data transmit is wrong

Answers: 0


body:
# Introduction
I am trying to program an arduino pro mini, I have to use this board because of it's size.
I use the arduino-cli to program arduino and one of the steps to upload code to the system requires the board's fqbn and I can't find it anywhere.
# Question
Does anybody know this board's fqbn (fully-qualified board name)?

title: arduino pro mini fqbn

Answers: 0


body:
    #include <Wire.h>
    #include <LiquidCrystal.h>
    int temp;
    const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
    LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
    char Nick[15] = {' ', ' ', 'T', 'A', 'R', 'I', 'F', ' ', 'Z', 'I', 'N', 'E', 'D', ' ', ' '};
    int butonPin = 2;

    void setup() {
      Wire.begin(1);
      Serial.begin(9600);
      pinMode(butonPin,INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(butonPin), Rev, RISING);
      lcd.begin(16, 2);
    }

    void loop() {
      Wire.onReceive(data);
      lcd.setCursor(2, 1);
      lcd.print(temp);

      if (temp < 25) {
        lcd.setCursor(5, 1);
        lcd.print("NORMAL");
        lcd.print(" ");
        lcd.setCursor(12, 1);
        lcd.print(" ");
      }
      if (temp >= 25 && temp <= 30) {
        lcd.setCursor(5, 1);
        lcd.print("HOT");
        lcd.print(" ");
        lcd.setCursor(11, 1);
        for (int i = 0 ; i < 3 ; i++) {
          lcd.print(" ");
        }
      }
      if (temp > 30) {
        lcd.setCursor(5, 1);
        lcd.print("VERY HOT");
        lcd.print(" ");
      }
      lcd.setCursor(0, 0);
      for (int j = 15; j > 0 ; j--) {
        lcd.print(Nick[j]);
      }
      lcd.setCursor(0, 0);
      delay(70);
      int swap = Nick[15];
      for (int i = 15; i > 0; i--) {
        Nick[i] = Nick[i - 1];
      }
      Nick[0] = swap;
    }
    void Rev(){
       Wire.onReceive(data);
      lcd.setCursor(2, 0);
      lcd.print(temp);

      if (temp < 25) {
        lcd.setCursor(5, 0);
        lcd.print("NORMAL");
        lcd.print(" ");
        lcd.setCursor(12, 0);
        lcd.print(" ");
      }
      if (temp >= 25 && temp <= 30) {
        lcd.setCursor(5, 0);
        lcd.print("HOT");
        lcd.print(" ");
        lcd.setCursor(11, 0);
        for (int i = 0 ; i < 3 ; i++) {
          lcd.print(" ");
        }
      }
      if (temp > 30) {
        lcd.setCursor(5, 0);
        lcd.print("VERY HOT");
        lcd.print(" ");
      }
      lcd.setCursor(0, 1);
      for (int j = 15; j > 0 ; j--) {
        lcd.print(Nick[j]);
      }
      lcd.setCursor(0, 1);
      delay(70);
      int swap = Nick[15];
      for (int i = 15; i > 0; i--) {
        Nick[i] = Nick[i - 1];
      }
      Nick[0] = swap;
    }

    void data(int numBytes) {
      while (Wire.available()) {
        temp = Wire.read();
      }
    }

In lcd's first line i have scrolling text.
Second line it shows current temperature and data from another master device.
My question is i want to change text line when button pressed and text shouldn't go back to old state it need to be stay in changed line and when the button repressed it change again
In my code when the button pressed several times lcd  gone weird : [![desc][1]][1]

I tried swap lines with lcd.setCursor() function :
In loop function :

    lcd.setCursor(0, 0);
          for (int j = 15; j > 0 ; j--) {
            lcd.print(Nick[j]);
          }
In reverse function :

    lcd.setCursor(0, 1);
      for (int j = 15; j > 0 ; j--) {
        lcd.print(Nick[j]);
      }
Thanks for answers guys

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

title: LiquidCrystal swap lines with interrupt

Answers: 0


body:
<!-- 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/ll5Uq.png)

<!-- End schematic -->

I am using an Arduino Uno, and WS2813 led strip (60 leds).

It seems like a default schematics (except I did use a 470 uF (electrolytical) cap instead of 1000 uF electrolytical cap.

(I accidantally marked the VCC pin of U1 VSS).

I don't get any LED of the LED strip glowing.

The program I used is:

    #include <FastLED.h>

    #define NUM_LEDS 60
    #define DATA_PIN 7

    CRGB leds[NUM_LEDS];
    bool led = false;

    void setup() {
        //FastLED.addLeds<WS2813, DATA_PIN>(leds, NUM_LEDS);
        FastLED.addLeds<WS2813, DATA_PIN>(leds, NUM_LEDS);
        pinMode(LED_BUILTIN, OUTPUT);
    }

    void loop()
    {
        for (int i = 0; i < NUM_LEDS; i++)
        {
          leds[i] = CRGB::Red;
        }
        FastLED.show();
        led = !led;
        digitalWrite(LED_BUILTIN, led ? HIGH : LOW);
        delay(1000);
    }

What I tried was:

- Checking different data pins on the Arduino
- Checking different wires
- Checking that over D7 and after the resistor there is indeed 330 Ohm resistance (it was 345 Ohm)
- Tried different data pins (and adapted the scene to use a different data pin)
- Checking that LED D1 is on (5V is flowing)
- Checking that at the end of the WS2813 there the VCC and GND 5V difference (it is about 5.1 V)
- Checking that there is indeed 5 V difference between the adapter + and - (was 5.2 V, unloaded).
- Tried with WS2813's BI grounded and unconnected
- Tried without the 330 ohm resistor.
- Checked with a the same circuit but WS2812B (and adapting the code to use WS2812B)
- Used different timings for the builtin LED to see that the sketch is actually uploaded.
- Tried with `, RGB)` added in line: `FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);`
- With a logic analyzer I see that every second there is a short burst of data (not analayzed exactly what, I assume FastLed is reliable).

All no difference.

However, what I did see, is the logic analyzer data AFTER the 330 ohm resistor mostly removes the data, while the data before the resistor is ok. However, when remove the resistance, still the LED strip does not light up.

Channel 0 is before the resistor, channel 1 after:

[![enter image description][1]][1]
What did I do wrong?

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

title: Why does my Arduino/Ledstrip combi not work?

Answers: 1

body:
It is important to connect the Arduino digital pin to the correct end of the LED strip.

LED strips have a unidirectional data line.

The power and ground connections can be made from either end, but the data IN is at one end and data OUT is at the other end.

That arrangement is for the purpose of daisychaining the LED strips.

The LEDs themselves also have data IN and data OUT, and are also daisychained with their neighbouring LEDs.

The LEDs are serially connected to each other through the data line, and are connected in parallel to the power and ground lines.


body:
[![here's an image of the wiring][1]][1]

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

So I have to do this project for school and it involves using a lcd display on tinkercad. I followed the wiring on this tutorial here: https://www.arduino.cc/en/Tutorial/HelloWorld. When I turn it on, the display is just blank even though I've tried to print.

Here is the code I have for this

    #include <Servo.h>
    #include <LiquidCrystal.h>

    //TESTING
    //ULTRASONIC WORKS
    //SERVO WORKS
    //BUZZER WORKS
    //POTENTIOMETER WORKS

    //Variables:

    Servo pump;

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

    bool blnPump = true;

    long lngTimer = 0;
    long lngDistance = 0;

    int intPumpTime = 0;
    int intLightLevel = 0;
    int intCount = 0;

    //soundDistance:to use the ultrasonic distance sensor and find the distance of an object above

    //input
     //intSignalPin: to indicate which pin to use for the sensor
    //output
     //lngDistance: the distance between the sensor and the object in cm

    long soundDistance (int intSignalPin)
    {
      long lngTime = 0;
      long lngDistance = 0;
      //gather the time is takes for the sound to travel back

      pinMode (intSignalPin, OUTPUT);
      digitalWrite (intSignalPin, LOW);
      delay (2);
      digitalWrite (intSignalPin, HIGH);
      delay (10);
      digitalWrite (intSignalPin, LOW);
      pinMode (intSignalPin, INPUT);
      lngTime = pulseIn (intSignalPin, HIGH);

      //Serial.println (lngTime);
      //calculating the distance

      lngDistance = lngTime * 0.01723;

      return lngDistance;
    }

    void setup()
    {
      pinMode (A0,INPUT);
      pinMode (A1, INPUT);
      pinMode (9, OUTPUT);
      pinMode(13, INPUT);
      Serial.begin (9600);

      pump.attach (10);

      lcd.begin(16, 2);
      lcd.print ("hello");
    }

    void loop()
    {
      //turning lcd off
      digitalWrite (8, LOW);

      lcd.print ("hello");
      //determining how many times the servo will pump
      intPumpTime = analogRead (A0);

      if (intPumpTime >= 0 && intPumpTime <= 341)
      {
        intPumpTime = 1;
      }

      else if (intPumpTime >= 342 && intPumpTime <= 683)
      {
        intPumpTime = 2;
      }

      else //if (intPumpTime >= 684 && intPumpTime <= 1023)
      {
        intPumpTime = 3;
      }

      //Pumping if theres a hand in range of 5cm to 25cm and pumping different amounts of sanitizer based on potentiometer, playing a tone if it does and turning the lcd on or off based on light level

      if (soundDistance (13) >= 5 && soundDistance (13) <= 25 && blnPump == true)
      {
        //turning lcd on or off
        intLightLevel = analogRead (A1);
        if (intLightLevel <= 300)
        {
          lcd.noDisplay();
        }

        else
        {
          lcd.display();
        }

        //playing tone to indicate its pumping
        tone (8, 500);
        delay (100);
        noTone (8);

        //lighting up led to indicate its pumping
        digitalWrite (9, HIGH);

        //pumping
        for (intCount = 0; intCount < intPumpTime; intCount++)
        {
        pump.write (90);
        delay (1000);
        pump.write (0);
        delay (1000);
        }

        //shutting off the led and turning the servo off
        digitalWrite (9, LOW);
        blnPump = false;

        lngTimer = millis();

        //waiting here to display hand scrubing time, no more sanitizer will be dispensed in this 20 seconds
        while (millis() - lngTimer < 20000)
        {

          if (millis() - lngTimer <= 1000)// && intLightLevel > 300)
          {
      lcd.clear();
            lcd.print ("19 seconds left");
          }

          else if (millis() - lngTimer > 4000 && millis() - lngTimer <= 5000)// && intLightLevel > 300)
          {
            //blnPump = true;
          }
        }

        //decide if to use LCD or not here
      }

      else
      {
        pump.write (0);
      }

      //Serial.println (soundDistance (13));
      //long lngTest = soundDistance (13);
    }

Sorry for all the extra code, they're for the other parts. I think I have followed what needs to be followed with inputting the pin into the LiquidCrystal class, the begin method but it just doesn't print.

title: LCD stays blank when it is on and all wiring seems correct

Answers: 0


body:
Serial link send and recieves Bytes. Serial monitor at Arduino IDE reads it's input as character.

So if I type '0' in serial monitor, then FW will read byte 48 - I don't want to implement some silly translation from character value to int - I want to input NUMBER as byte into serial monitor - how do I do that?

    byte inByte = Serial.read(); // read the incoming byte
    if(inByte == 1) // do stuff

title: Arduino IDE Serial Monitor - how to send NUMBERs - not charcters of numbers

Answers: 2

body:
Based on comments under question no one seems to really know the answer.

So the short answer is: **IT'S IMPOSSIBLE** - to use Arduino IDE serial monitor to send raw data.

@Edgar_Bonet submitted hint for linux users

@jsotola suggested to use PuTTY, but no additional info on how to do that. Short glance at settings and I couldn't find the way to achieve raw input.

After some additional googling i found some [reading][1] where I found program called [RealTerm][2] which does the job.

Simply setup your port on *Port* card and then hit *Change* button.

On card *Display* change *Display As* From ASCII to your prefered format, such as Hex(space)

Then swich on card Send - type your number into input box left to button *Send Numbers* and press that button

Thats all

The input box accepts decimal value from 0 to 255, or a hexadecimal value, which are prefixed with either a "0x" or a '$'. Each value is separated by space.

Following line is correctly accepted: "255 0xff 0xFF $ff $FF"

Yet another useful tool is [Serial Port Monitor][3]. With this you can observe what is really transmitted on line without relying on the interpretation of you application.

Usage is really simple: click white file icon, or Session > New session or press
Ctrl+N

Choose port and vizualizer and click Start monitoring... that's it.

I found most useful mode "Dump view"

  [1]: https://learn.sparkfun.com/tutorials/terminal-basics/real-term-windows
  [2]: https://sourceforge.net/projects/realterm/
  [3]: https://www.com-port-monitoring.com/

body:
I think the comments on your question are quite clear. The important point: any asynchronuous protocoll *must* include the info either *how many* bytes are transmitted or which byte is *the last one*. In "raw data", where each value (0-255) can be a legit data value, there is no way to use bytes for meta data. That's why typically only encoded data is transmitted: you have a small range of byte values that can contain the actual info (alphabet and digits) and you have a bunch of values that are free to be used as meta data. E.g. the commonly used `\n` as endbyte has the int value 10. How would you transmit the int value 10 in that case?

"I don't want to implement some silly translation from character value to int" - it's not silly, that's the way to go! What about float, boolean or negative values (8-bit, 16-bit, etc.)? You may even want to transmit structured data like python dictionaries. The only way the achieve this is using some kind of parser which knows the protocol.


body:
In short. ESP32, two water meters (hot and cold). Booth, hot and cold, some interrupts are missed. When i connect ESP32 to serial monitor and watch then all interrupts are detected (about 5-10 minutes). But if i leave to 5v power only, then some interrupts are missed (in one day it can be up to 50 or even more).

About [water counter][1] - one pulse per liter. Correct info about sensor is in PDF [Original Operating Instructions][2].  [![Here is image of technical info][3]][3]

Sensor connections. Brown wire to GND, white to PIN 32(hot),33(cold).

**Board**. Olimex [ESP32-POE][4] Rev C.

 - Powered via 5v Samsung phone charger (standard 5V charger without 9v)
 - WiFi enabled (For NTP and to see counter readings)
 - OTA enabled
 - [WEB server running][5] (plain html, ESPAsyncWebServer)
 - Bluetooth disabled
 - SD card attached (stores SQLite database only)
 - Uses [ siara-cc/esp32_arduino_sqlite3_lib ][6] library

**Water usage in last month (May)**

 - hot - 4777 liters (counted with sensor - 2675)
 - cold - 9289, with sensor - 5528

As we can see, difference is huge. Maybe ISR routine exec time is too long and some interrupts are skipped? I know that WiFi too uses interrupts... Is my interrupt code wrong? Water counter reading is stored in SQLite database when 10 liters are used. Thanks for anyone for your time in advance!

Here is image of water counter and sensor [![image of water counter and sensor][7]][7]

Here is some code, related to interrupts (debug disabled).

    struct WaterCounter
    {
      const uint8_t PIN; // microcontroller pin...
      volatile uint32_t liters_total; // max 4294967295
      volatile uint16_t liters_in_session; // max 65535
      volatile uint32_t session_started; // unix timestamp
      volatile uint32_t session_last_pulse; // unix timestamp
      const char display_name[5];
      volatile unsigned long pulse_start;
      volatile unsigned long pulse_stop;
      volatile uint32_t isr_prev_time;
      volatile uint32_t liters_last_written;
      volatile uint32_t liters_used_today;
    };
    WaterCounter wc_hot =  { PIN_WC_HOT, 0, 0, 0, 0, "Hott", 0, 0, 0, 0, 0 };
    WaterCounter wc_cold = {PIN_WC_COLD, 0, 0, 0, 0, "Cold", 0, 0, 0, 0, 0 };
    void IRAM_ATTR handle_wc(WaterCounter *wc)
    {
      uint32_t  t = micros();
      uint32_t dt = t - wc->isr_prev_time;
      if (dt<1500) return;
      wc->isr_prev_time = t;
      if (wc->pulse_start == 0)
      {
        wc->pulse_start = millis();
        #ifdef DEBUG_ISR
          //Serial.printf("Started %s pulse!\n", wc->display_name);
          ets_printf("Started %s pulse!\n", wc->display_name);
        #endif
      }else
      {
        wc->pulse_stop = millis();
        unsigned long pulsew = wc->pulse_stop - wc->pulse_start;
        wc->pulse_start = 0;
        if (pulsew > 40 && pulsew < 55)
        {
          wc->liters_total++;
          wc->liters_in_session++;
          wc->liters_used_today++;
          if (wc->session_started == 0)
          {
            wc->session_started = now;
          }
          wc->session_last_pulse = now;
        }
        #ifdef DEBUG_ISR
          //Serial.printf("%s: pulse_width: %ld\n", wc->display_name, pulsew);
          ets_printf("%s: pulse_width: %ld\n", wc->display_name, pulsew);
        #endif
      }
    }
    void IRAM_ATTR isr_wc_cold()
    {
      handle_wc(&wc_cold);
    }

    void IRAM_ATTR isr_wc_hot()
    {
      handle_wc(&wc_hot);
    }

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

      // allow some time to pull up pin, interrupt is attached below
      pinMode(wc_cold.PIN, INPUT_PULLUP);
      pinMode(wc_hot.PIN, INPUT_PULLUP);

      Serial.printf("Watchdog timeout: %dms\n", WATCHDOG_TIMEOUT);
      timerWD = timerBegin(0, 80, true);                  //timer 0, div 80
      timerAttachInterrupt(timerWD, &resetModule, true);  //attach callback
      timerAlarmWrite(timerWD, WATCHDOG_TIMEOUT * 1000, false); //set time in us
      timerAlarmEnable(timerWD); //enable interrupt
      timerWrite(timerWD, 0); //reset timer (feed watchdog)

      SD_MMC.begin();

      enqRC = sqlite3_initialize();
      if (enqRC == SQLITE_OK)
      {
        openDb();
        initSensorDatabase();
        timerWrite(timerWD, 0); //reset timer (feed watchdog)
        SetupWiFi();
        closeDb();
      }
      timerWrite(timerWD, 0); //reset timer (feed watchdog)
      pollNtp();
      timerWrite(timerWD, 0); //reset timer (feed watchdog)

      openDb();
      initTotalValues(&wc_cold);
      timerWrite(timerWD, 0); //reset timer (feed watchdog)
      initTotalValues(&wc_hot);
      closeDb();
      timerWrite(timerWD, 0); //reset timer (feed watchdog)

      attachInterrupt(digitalPinToInterrupt(wc_cold.PIN), &isr_wc_cold, FALLING);
      attachInterrupt(digitalPinToInterrupt(wc_hot.PIN), &isr_wc_hot, FALLING);

      timer_session = timerBegin(1, 80, true);
      timerAttachInterrupt(timer_session, &onSessionTimer, true);
      timerAlarmWrite(timer_session, 1000000, true); // every 1 second
      timerAlarmEnable(timer_session);

      EnableOTA();

      //* async web
      webServer.on("/", HTTP_GET, handleRootAsync);
      webServer.on("/heap", HTTP_GET, heapInfoAsync);
      webServer.on("/post", HTTP_POST, handlePostAsync);
      webServer.on("/params", HTTP_GET, handleParameterPage);
      webServer.onNotFound(onNotFoundAsync);
      webServer.begin();

      time(&now);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      loop_task();
    }
    void loop_task()
    {
      if (time_every_second <= now)
      {
        writeWcTotalToDb(&wc_cold);
        writeWcTotalToDb(&wc_hot);
        time_every_second = now + 1;
      }

      if (time_every_30_seconds <= now)
      {
        pollNtp();
        time_every_30_seconds = now + 30;
      }
    }
    void IRAM_ATTR finishSession(WaterCounter *wc, time_t tt)
    {
      if (wc->session_started == 0)
      {
        return;
      }
      if (tt - wc->session_last_pulse > SESSION_LENGHT)
      {
        //finish session
        #ifdef DEBUG_ISR
          //Serial.printf("# %s liters in session: %d, duration %d(s)\n", wc->display_name, wc->liters_in_session, wc->session_last_pulse - wc->session_started);
          ets_printf("# %s liters in session: %d, duration %d(s)\n", wc->display_name, wc->liters_in_session, wc->session_last_pulse - wc->session_started);
        #endif

        wc->session_started = 0;
        wc->liters_in_session = 0;
      }
    }

    /* every 1s  */
    void IRAM_ATTR onSessionTimer()
    {
      timerWrite(timerWD, 0); //reset timer (feed watchdog)
      //ets_printf("\nonSessionTimer()\n");
      time(&now);
      getLocalTime(&timeinfo);
      strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%d %H:%M:%S", &timeinfo);
      if (now % 86400 == 75600) /* works if this function is called every second */
      {
        ets_printf("\n!!!midnight!!\n");
        wc_cold.liters_used_today = 0;
        wc_hot.liters_used_today = 0;
      }
      finishSession(&wc_cold, now);
      finishSession(&wc_hot, now);
    }
    void writeWcTotalToDb(WaterCounter *wc)
    {
      #ifdef DEBUG_WRITE
        Serial.printf("writeWcTotalToDb(%s): begin\n", wc->display_name);
      #endif

      uint8_t ldiff = wc->liters_total - wc->liters_last_written;
      if (ldiff == 0)
      {
        #ifdef DEBUG_WRITE
          Serial.println("writeWcTotalToDb(): diff zero");
        #endif
        return;
      }
      if (ldiff <= LITERS_BEFORE_WRITE && wc->session_started > 0)
      {
        #ifdef DEBUG_WRITE
          Serial.println("writeWcTotalToDb(): ldiff <= LITERS_BEFORE_WRITE && wc->session_started > 0");
        #endif
        return;
      }
      #ifdef DEBUG_WRITE
        Serial.println("writeWcTotalToDb(): start writting procedure!");
      #endif
      if (!openDb())
      {
        char *sql = "INSERT INTO `water_counter` VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        sqliteResultCode = sqlite3_prepare_v2(sqliteDb, sql, strlen(sql), &sqliteRes, NULL);
        if (sqliteResultCode != SQLITE_OK)
        {
          #ifdef DEBUG
            Serial.printf("writeWcTotalToDb(): ERROR preparing sql: %d -> %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
          #endif
        }else
        {
          #ifdef DEBUG
            Serial.print("writeWcTotalToDb(): Prepare OK\n");
          #endif
          //getLocalTime(&timeinfo); // inside every 1 sec
          //strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%d %H:%M:%S", &timeinfo);
          sqlite3_bind_int(sqliteRes, 1, now); // datums
          sqlite3_bind_int(sqliteRes, 2, wc->liters_total);
          sqlite3_bind_text(sqliteRes, 3, timeStringBuff, strlen(timeStringBuff), SQLITE_STATIC);
          sqlite3_bind_text(sqliteRes, 4, wc->display_name, strlen(wc->display_name), SQLITE_STATIC);
          sqlite3_bind_int(sqliteRes, 5, 0);
          sqlite3_bind_int(sqliteRes, 6, wc->liters_in_session);
          sqlite3_bind_int(sqliteRes, 7, wc->session_started);
          sqlite3_bind_int(sqliteRes, 8, 0); /* currently not used */

          if (sqliteResultCode = sqlite3_step(sqliteRes) != SQLITE_DONE)
          {
              #ifdef DEBUG
                Serial.printf("writeWcTotalToDb(): ERROR executing stmt: %d -> %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
              #endif
          }else
          {
              #ifdef DEBUG
                Serial.print("writeWcTotalToDb(): data saved!\n");
              #endif
              wc->liters_last_written = wc->liters_total;
              sqlite3_clear_bindings(sqliteRes);
              sqliteResultCode = sqlite3_reset(sqliteRes);
              if (sqliteResultCode != SQLITE_OK)
              {
                #ifdef DEBUG
                  Serial.printf("writeWcTotalToDb(): sqlite3_reset(res) result code = [%s] %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
                #endif
              }else
              {
                #ifdef DEBUG
                  Serial.print("writeWcTotalToDb(): sqlite3_reset(res) OK\n");
                #endif
              }
              sqlite3_finalize(sqliteRes);
          }
        }
        closeDb();
      }else
      {
        #ifdef DEBUG
          Serial.println("writeWcTotalToDb(): Failed to open database!");
        #endif
      }
      #ifdef DEBUG_WRITE
        Serial.printf("writeWcTotalToDb(%s): finished!\n", wc->display_name);
      #endif
    } /* writeWcTotalToDb() */

  [1]: https://www.wehrle.de/en/metering/remote-reading/modularis-modules/
  [2]: https://www.wehrle.de/wp-content/uploads/2016/11/161118-Kurzanleitung-Impulsmodul-Modularis-06-EN.pdf
  [3]: https://i.stack.imgur.com/fMraU.png
  [4]: https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/
  [5]: https://github.com/me-no-dev/ESPAsyncWebServer/
  [6]: https://github.com/siara-cc/esp32_arduino_sqlite3_lib
  [7]: https://i.stack.imgur.com/PYTrb.jpg

title: Esp32 external interrupts sometime is missing

Answers: 2

body:
As @Majenko suggested, i created solution with pulse counter.

Here is working code, based on [espressif PCNT Example][1]. Arduino studio, Olimex ESP32-POE board.

Each water meter uses separate pulse counter unit. Now I am testing this code and after several days i will accept answer if all works like i want :)

    #include "freertos/queue.h"
    #include "driver/pcnt.h"
    #include "driver/periph_ctrl.h"
    #include "driver/gpio.h"
    #include "esp_attr.h"

    #define PCNT_H_LIM_VAL      1
    #define PCNT_L_LIM_VAL     -1
    #define PCNT_THRESH1_VAL    0
    #define PCNT_THRESH0_VAL   -0
    #define PCNT_INPUT_SIG_WC_HOT   32 // hot water counter
    #define PCNT_INPUT_SIG_WC_COLD  33 // cold water counter
    /*
    Cold meter uses PCNT_UNIT_1
    hot meter uses PCNT_UNIT_0
    */
    xQueueHandle pcnt_evt_queue;   // A queue to handle pulse counter events
    pcnt_isr_handle_t user_isr_handle = NULL; //user's ISR service handle

    /* A sample structure to pass events from the PCNT
     * interrupt handler to the main program.
     */
    typedef struct {
        pcnt_unit_t unit;  // the PCNT unit that originated an interrupt
        uint32_t status; // information on the event type that caused the interrupt
    } pcnt_evt_t;

    /* Decode what PCNT's unit originated an interrupt
     * and pass this information together with the event type
     * the main program using a queue.
     */
    static void IRAM_ATTR pcnt_example_intr_handler(void *arg)
    {
        uint32_t intr_status = PCNT.int_st.val;
        int i;
        pcnt_evt_t evt;
        portBASE_TYPE HPTaskAwoken = pdFALSE;

        for (i = 0; i < PCNT_UNIT_MAX; i++) {
            if (intr_status & (BIT(i))) {
                evt.unit = (pcnt_unit_t)i;
                /* Save the PCNT event type that caused an interrupt
                   to pass it to the main program */
                evt.status = PCNT.status_unit[i].val;
                PCNT.int_clr.val = BIT(i);
                xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
                if (HPTaskAwoken == pdTRUE) {
                    portYIELD_FROM_ISR();
                }
            }
        }
    }

    /* Initialize PCNT functions:
     *  - configure and initialize PCNT
     *  - set up the input filter
     *  - set up the counter events to watch
     */
    static void pcnt_example_init()
    {
        //Serial.printf("pcnt_example_init(%d, %d)\n", _unit, _pin);
        /* Prepare configuration for the PCNT unit */
        pcnt_config_t pcnt_config = {};
        pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_WC_HOT;
        pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
        pcnt_config.channel = PCNT_CHANNEL_0;
        pcnt_config.pos_mode = PCNT_COUNT_INC;
        pcnt_config.neg_mode = PCNT_COUNT_DIS;
        pcnt_config.lctrl_mode = PCNT_MODE_KEEP;//PCNT_MODE_REVERSE;
        pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
        pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
        pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;
        pcnt_config.unit = PCNT_UNIT_0;

        /* Initialize PCNT unit */
        ESP_ERROR_CHECK(pcnt_unit_config(&pcnt_config));

        /* cold water meter */
        pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_WC_COLD;
        pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
        pcnt_config.channel = PCNT_CHANNEL_0;
        pcnt_config.pos_mode = PCNT_COUNT_INC;
        pcnt_config.neg_mode = PCNT_COUNT_DIS;
        pcnt_config.lctrl_mode = PCNT_MODE_KEEP;//PCNT_MODE_REVERSE;
        pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
        pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
        pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;
        pcnt_config.unit = PCNT_UNIT_1;
        ESP_ERROR_CHECK(pcnt_unit_config(&pcnt_config));

        /* Configure and enable the input filter */
        ESP_ERROR_CHECK(pcnt_set_filter_value(PCNT_UNIT_0, 1000)); // filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
        ESP_ERROR_CHECK(pcnt_filter_enable(PCNT_UNIT_0));

        /* Set threshold 0 and 1 values and enable events to watch */
        ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1));
        ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
        /* Enable events on zero, maximum and minimum limit values */
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_ZERO));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_L_LIM));

        /* Initialize PCNT's counter */
        ESP_ERROR_CHECK(pcnt_counter_pause(PCNT_UNIT_0));
        ESP_ERROR_CHECK(pcnt_counter_clear(PCNT_UNIT_0));

        /* Register ISR handler and enable interrupts for PCNT unit */
        ESP_ERROR_CHECK(pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, &user_isr_handle));
        ESP_ERROR_CHECK(pcnt_intr_enable(PCNT_UNIT_0));

        /* Everything is set up, now go to counting */
        ESP_ERROR_CHECK(pcnt_counter_resume(PCNT_UNIT_0));

        /* PCNT_UNIT_1 configuration  */
        /* Configure and enable the input filter */
        ESP_ERROR_CHECK(pcnt_set_filter_value(PCNT_UNIT_1, 1000)); // filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
        ESP_ERROR_CHECK(pcnt_filter_enable(PCNT_UNIT_1));

        /* Set threshold 0 and 1 values and enable events to watch */
        ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_1, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_THRES_1));
        ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_1, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_THRES_0));
        /* Enable events on zero, maximum and minimum limit values */
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_ZERO));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_H_LIM));
        ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_L_LIM));

        /* Initialize PCNT's counter */
        ESP_ERROR_CHECK(pcnt_counter_pause(PCNT_UNIT_1));
        ESP_ERROR_CHECK(pcnt_counter_clear(PCNT_UNIT_1));

        ESP_ERROR_CHECK(pcnt_intr_enable(PCNT_UNIT_1));

        /* Everything is set up, now go to counting */
        ESP_ERROR_CHECK(pcnt_counter_resume(PCNT_UNIT_1));
    }

    void setup() {
      Serial.begin(115200);
      Serial.println("Boot...");
      // put your setup code here, to run once:
      pinMode(PCNT_INPUT_SIG_WC_HOT, INPUT_PULLUP);
      pinMode(PCNT_INPUT_SIG_WC_COLD, INPUT_PULLUP);
      /* Initialize PCNT event queue and PCNT functions */
      pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));

      pcnt_example_init();
      //  pcnt_example_init(PCNT_UNIT_WC_HOT, PCNT_INPUT_SIG_WC_HOT);
        //pcnt_example_init(PCNT_UNIT_WC_COLD, PCNT_INPUT_SIG_WC_COLD);

        Serial.printf("Setup done\n");
    }

    int16_t count = 0;
    pcnt_evt_t evt;
    portBASE_TYPE res;

    char * chToName(int ch)
    {
      if (ch == 1) return "Cold";
      if (ch == 0) return "Hot";

      return "Unc";
    }

    void loop() {
      // put your main code here, to run repeatedly:
          /* Wait for the event information passed from PCNT's interrupt handler.
             * Once received, decode the event type and print it on the serial monitor.
             */
            res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
            if (res == pdTRUE) {
                pcnt_get_counter_value(evt.unit, &count);
                Serial.printf("Event PCNT unit[%d=%s]; cnt: %d, status: %d\n", evt.unit, chToName(evt.unit), count, evt.status);
                if (evt.status & PCNT_EVT_THRES_1) {
                    Serial.printf("THRES1 EVT\n");
                }
                if (evt.status & PCNT_EVT_THRES_0) {
                    Serial.printf("THRES0 EVT\n");
                }
                if (evt.status & PCNT_EVT_L_LIM) {
                    Serial.printf("L_LIM EVT\n");
                }
                if (evt.status & PCNT_EVT_H_LIM) {
                    Serial.printf("H_LIM EVT\n");
                }
                if (evt.status & PCNT_EVT_ZERO) {
                    Serial.printf("ZERO EVT\n");
                    // here we are increment liter count
                }
            } else {
                pcnt_get_counter_value(PCNT_UNIT_0, &count);
                Serial.printf("Current counter value: %s=%d,", chToName(PCNT_UNIT_0), count);
                pcnt_get_counter_value(PCNT_UNIT_1, &count);
                Serial.printf(" %s=%d\n", chToName(PCNT_UNIT_1), count);
                //pcnt_get_counter_value(PCNT_UNIT_WC_COLD, &count);
                //Serial.printf(", %d on unit: %d\n", count, PCNT_UNIT_WC_COLD);
            }

            /*
            if(user_isr_handle) {
              Serial.printf("Clearing user_isr_handle\n");
              //Free the ISR service handle.
              esp_intr_free(user_isr_handle);
              user_isr_handle = NULL;
            }*/
    }

  [1]: https://github.com/espressif/esp-idf/blob/7d75213674b4572f90c68162ad6fe9b16dae65ad/examples/peripherals/pcnt/main/pcnt_example_main.c

body:
You can use Pulse Counter(PCNT) feature in ESP32 to count the number of pulse in background, Its also possible to configure event when number of counts reached certain threshold and had lot of options,

For get information and available Interfaces and API's for Pulse Counter(PCNT) please follow below link, https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html

> Initially I faced lot of issue to make **Pulse Counter(PCNT)** work in Adrino IDE for ESP-32, After multiple attempt I make it working, And same  sample code is uploaded in GitHub for reference. I have not use all the API's in the official documentation but but used few of them and are working..

I have created a simple sample program for a water flow meter, there also we use to get pulse which needs to count to measure the water flow rate.

GitHub Sample code Path:- https://github.com/Embedded-Linux-Developement/Arduino_Sample_Programs/tree/main/ESP_32/Water_Flow_Pulse_counter_WithOut_Interrupt_Using_PCNT

I have not placing the code here, because its there in GitHub and a simile one and can use it. Its a working code I tested in ESP32 HW.

*Hopes Its helpful,
Regards, Jerry James*


body:
I wrote an Arduino Matrix class. Then I used this class to implement State Space on Arduino.
During tests I stomped upon a problem. After starting the program it stops at some point. I have no idea why this is happening. There are no error messages.
Can you please tell me what im doing wrong?

Here is my code:
```
//"Matrix.h"
#ifndef _Matrix_h
#define _Matrix_h

#if defined(ARDUINO) && ARDUINO >= 100
 #include "arduino.h"
#else
 #include "WProgram.h"
#endif
class Matrix
{
private:
    unsigned row_number = 0;
    unsigned column_number = 0;
    double* elems;

public:

    //Constructors + Destructor
    Matrix();
    Matrix(double, unsigned row_number = 1, unsigned column_number = 1);
    Matrix(double*, unsigned row_number = 1, unsigned column_number = 1);
    Matrix(const char*);
    Matrix(const Matrix&);
    void operator=(Matrix);
    ~Matrix();

    //Comunication Methods
    unsigned get_rows() const { return row_number; };
    unsigned get_columns() const { return column_number; };
    double& operator()(const unsigned row, const unsigned column);
    double valueAt(unsigned row, unsigned column) const ;
    void print() const;
    bool mRead2();

    //Matrix Operations
    Matrix operator+(Matrix);
    Matrix operator-(Matrix);
    Matrix operator*(Matrix);
    Matrix transpose();

    //Scalar Operations
    Matrix operator+(double);
    Matrix operator-(double);
    Matrix operator*(double);
    Matrix operator/(double);

};
Matrix mRead(unsigned row,unsigned column);
#endif
```
```
//"Matrix.cpp"

#include "Matrix.h"
Matrix::Matrix() {
  row_number = 0;
  column_number = 0;
  elems = new double[0];
}
Matrix::Matrix(double val, unsigned row_number, unsigned column_number) {
  this->row_number = row_number;
  this->column_number = column_number;
  elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i < row_number * column_number + 1; i++)
    elems[i] = val;

}

Matrix::Matrix(double* elems, unsigned row_number, unsigned column_number)
{
  this->column_number = column_number;
  this->row_number = row_number;
  this->elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i < row_number * column_number + 1; i++)
    this->elems[i] = elems[i - 1];
}

Matrix::Matrix(const char*)
{

}

void Matrix::operator=(Matrix A){
  this->column_number = A.get_columns();
  this->row_number = A.get_rows();
  this->elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      this->elems[(i - 1) * (column_number) + j] =  A.valueAt(i, j);

}

Matrix::Matrix(const Matrix& A) {
  this->column_number = A.get_columns();
  this->row_number = A.get_rows();
  elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      this->elems[(i - 1) * (column_number) + j] =  A.valueAt(i, j);

}

Matrix::~Matrix()
{
  delete[] elems;
}

double& Matrix::operator()(const unsigned row, const unsigned column)
{

    return this->elems[(row - 1) * (column_number) + column ];

}

double Matrix::valueAt(unsigned row, unsigned column) const
{

    return this->elems[(row - 1) * (column_number) + column ];

}

void Matrix::print() const
{
  for (unsigned i = 1; i <= get_rows(); i++) {
    for (unsigned j = 1; j <= get_columns(); j++) {
      Serial.print(this->valueAt(i, j));
      Serial.print(" ");
      Serial.flush();
    }
    Serial.print("\n");
  }
}
Matrix mRead(unsigned row, unsigned column) {
  int sizeM = row * column;
  double m[sizeM];
  char buffor[64];
  for (int i = 0; i < 64; i++) {
    buffor[i] = 0;
  }
  for (int i = 0; i < sizeM; i++) {m[i]=0;}
  for (int i = 0; i < sizeM; i++) {
    while (!Serial.available()) {
      Serial.write(32);
    }
    int j = 0;
    while (Serial.available() > 0) {
      Serial.println(Serial.available());
      buffor[j] = Serial.read();
      j++;
      Serial.flush();
    }
    m[i] = (double)atof(buffor);
    Serial.flush();
    //for (int i = 0; i < 64; i++) {
    //  buffor[i] = 0;
    //}
  }
  return Matrix(m, row, column);
}
bool Matrix::mRead2() {
  int sizeM = row_number * column_number;
  double m[sizeM];
  char buffor[64];
  for (int i = 0; i < 64; i++) {
    buffor[i] = 0;
  }
  for (int i = 0; i < sizeM; i++) {m[i]=0;}
  for (int i = 0; i < sizeM; i++) {
    while (!Serial.available()) {
      Serial.write(32);
    }
    int j = 0;
    while (Serial.available() > 0) {
      Serial.println(Serial.available());
      buffor[j] = Serial.read();
      j++;
      Serial.flush();
    }
    m[i] = (double)atof(buffor);
    Serial.flush();
    for (int i = 0; i < 64; i++) {
      buffor[i] = 0;
    }
  }
  *this=Matrix(m,row_number,column_number);
  return true;
}
Matrix Matrix::operator+(Matrix A)
{
    Matrix sum = Matrix(0.0, row_number, column_number);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        sum(i, j) = A.valueAt(i, j) + this->valueAt(i, j);

    return sum;
}

Matrix Matrix::operator-(Matrix A)
{
    Matrix diff = Matrix(0.0, row_number, column_number);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        diff(i, j) = A.valueAt(i, j) + this->valueAt(i, j);
    return diff;

}

Matrix Matrix::operator*(Matrix A)
{
  Matrix mult = Matrix(0.0, row_number, A.get_columns());
    double temp;
    for (unsigned i = 1; i <= row_number; i++) {
      for (unsigned j = 1; j <= A.get_columns(); j++) {
        temp = 0.0;
        for (unsigned k = 1; k <= column_number; k++)
          temp += this->valueAt(i, k) * A(k, j);
        mult(i, j) = temp;
      }
    }

    return mult;
}

Matrix Matrix::transpose() {
  Matrix transpose = Matrix(0.0, row_number, column_number);
  for (unsigned i = 1; i <= row_number; i++) {
    for (unsigned j = 1; j <= column_number; j++) {
      transpose(i, j) = this->valueAt(j, i);
    }
  }
  return transpose;
}

Matrix Matrix::operator+(double x)
{
  Matrix A = Matrix(x, row_number, column_number);
  return *this + A;
}

Matrix Matrix::operator-(double x)
{
  Matrix A = Matrix((-1) * x, row_number, column_number);
  return *this + A;
}

Matrix Matrix::operator*(double x)
{
  Matrix A = Matrix(*this);
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      A(i, j) = this->valueAt(i, j) * x;
  return A;

}

Matrix Matrix::operator/(double x)
{
  if (x != 0) {
    Matrix A = Matrix(*this);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        A(i, j) = this->valueAt(i, j) / x;
    return A;
  }
  else {} //throw "Dividing by zero";
}
```
```
//"StateSpace.h"

#ifndef _StateSpace_h
#define _StateSpace_h
#include "C:\Users\Wojciech Trybulec\Desktop\Test\Matrix.h"
class StateSpace
{
private:
    Matrix State;
    Matrix A;
    Matrix B;
    Matrix C;
    Matrix D;
    Matrix Out;
public:

    //Constructors + Destructor
    StateSpace();
    StateSpace(Matrix A, Matrix B, Matrix C, Matrix D);
    StateSpace(Matrix A, Matrix B, Matrix C, Matrix D,Matrix InitState);
    StateSpace(const StateSpace&);
    StateSpace operator=(StateSpace);
    ~StateSpace();

    //Comunication Methods
    Matrix get_states() const;
    Matrix get_output() const;
    Matrix* get_all() const;
    void calculate(Matrix Signal);
    void print_states() const;
    void print_output() const;
    void print_matrices() const;

};
#endif
```
```
//"StateSpace.cpp"
#include "C:\Users\Wojciech Trybulec\Desktop\Test\Matrix.h"
#include "StateSpace.h"
StateSpace::StateSpace() {
    A = Matrix();
    B = Matrix();
    C = Matrix();
    D = Matrix();
    State = Matrix();
    Out = Matrix();
}
StateSpace::StateSpace(Matrix A, Matrix B, Matrix C, Matrix D) {
    this->A = A;
    this->B = B;
    this->C = C;
    this->D = D;
    this->State = Matrix(0.0,A.get_columns(),1);
    this->Out = Matrix(0.0, C.get_rows(), 1);
}
StateSpace::StateSpace(Matrix A,Matrix B, Matrix C, Matrix D,Matrix InitState){
    this->A = A;
    this->B = B;
    this->C = C;
    this->D = D;
    this->State = InitState;
    this->Out = Matrix(0.0, C.get_rows(), 1);
}
StateSpace::StateSpace(const StateSpace& ss) {
    this->A = ss.get_all()[0];
    this->B = ss.get_all()[1];
    this->C = ss.get_all()[2];
    this->D = ss.get_all()[3];
    this->State = ss.get_all()[4];
    this->Out = ss.get_all()[5];
}
StateSpace StateSpace::operator=(StateSpace ss) {
    this->A = ss.get_all()[0];
    this->B = ss.get_all()[1];
    this->C = ss.get_all()[2];
    this->D = ss.get_all()[3];
    this->State = ss.get_all()[4];
    this->Out = ss.get_all()[5];
}
StateSpace::~StateSpace() {
    delete this;
    //A.~Matrix;
    //B.~Matrix;
    //C.~Matrix;
    //D.~Matrix;
    //State.~Matrix;
    //Out.~Matrix;
}

Matrix StateSpace::get_states() const {
    return this->State;
}
Matrix StateSpace::get_output() const{
    return this->Out;
}
Matrix* StateSpace::get_all() const {
    Matrix all[6];
    all[0] = A;
    all[1] = B;
    all[2] = C;
    all[3] = D;
    all[4] = State;
    all[5] = Out;
    return all;

}
void StateSpace::calculate(Matrix Signal) {
    State = ((A * State) + (B * Signal));
    Out = ((C * State) + (D * Signal));
}
void StateSpace::print_states() const {
    State.print();
}
void StateSpace::print_output() const {
    Out.print();
}
void StateSpace::print_matrices() const {
    A.print();
    B.print();
    C.print();
    D.print();
}
```
And this Arduino sketch that im using for testing:
```
#include "Matrix.h"
#include "StateSpace.h"
double a[4]={-0.5,0,0,0.7};
double b[2]={1,2};
double c[4]={1,0,0,1};
double d = 0;
Matrix A=Matrix(a,2,2);
Matrix B=Matrix(b,2,1);
Matrix C=Matrix(c,2,2);
Matrix D=Matrix(d,1,1);
Matrix x=Matrix(0.0,2,1);
Matrix U=Matrix(1.0,1,1);
StateSpace ss=StateSpace(A,B,C,D);
void setup()
{
  Serial.begin(9600);
}
void loop() {
  ss.calculate(U);
  x=ss.get_states();
  Serial.print(x.valueAt(1,1));
  Serial.print("\t");
  Serial.println(x.valueAt(2,1));

  delay(100);
}
```
I really hope that you can help me

title: Matrix and State Space Arduino Implementation

Answers: 1

body:
This is not a solution (meaning to pinpoint the exact problem), but to find out yourself.
There are mainly two ways to debug this:

1. On Arduino: Try placing `Serial.print` statements to see where it stops (like putting them on the beginning of every function, or on other 'strategic' places. When you found which function stops, try putting `print` statements within. So within two 'runs' you can find which line is causing the problem. What I normally do is just number the print statements, e.g. function 1 you print values 100..200, next function 200.300 etc. So you can easily leave them for later reusage (just comment them out).

2. Unit test on PC: If you didn't already do, test your class on a PC... this will give you much better debugging tools than an Arduino. When you know the class itself work, create a small test sketch on the Arduino (but high likely it will work, unless you made a mistake in the test sketch). For a PC, consider writing a so-called unit-test ... so even later when you change something, you can test you didn't break anything else.

In both cases (if you start on PC also do this), check for memory usage. The Arduino has only 2 KB SRAM, on a PC you can already check how much is used. The SRAM usage shown during compiling only takes into account global variables. It does not take into account:

- Local variables
- Dynamic variables (made with `new`, `malloc`)
- Stack (passed parameters).


body:
first of all, Im from Cuba, that means I may have some problems to find parts...

I have a little system to measure the water level in my house water tank. The system is pretty rough: a proximity sensor HC-SR04 well fixed in the top of the tank, some long wires to an ArduinoNano, and a LCD screen where I display information as: water level in liters and in %.

The problem is the proximity sensor HC-SR04 seems to be broken now, not work at all and I was thinking in replace it by raw cables

Something like in the image below, but maybe with more steps:
[![enter image description here][1]][1]

So... My questions are:

-Is this posible? I just test it with a glass of water and two short wires and it work, but sometimes it throw me some falses-positives... It may be my code: just light on a led if digitalpin X is high when I put two wires in the water (1 wire to arduino 5V pin and the other to the digitalpin I wanna check if is high), and it do it, but when I pull out the wires the led stay on for more than a few seconds.

-If it is posible, how long can be the wire? Is 10m ok?

Thanks

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

title: Trying a crude water level sensor

Answers: 1

body:
As others have said, you need to make sure you have pull-up or pull-down resistors on all digital inputs so their value doesn't "float" (fluctuate between high and low.)

Given that water tanks and wells tend to be strongly earth grounded, I would suggest some changes:

Change the common wire to a ground, not +5V

Change all of your other pins to analog inputs. Connect them to high ohm pull-up resistors (say 10kΩ). They will read a full 5V when their ends are not in water. When the water rises and the ends dip into the water, their voltages will drop. Use analog readings to detect those voltage drops.

You could also use something like graphite a pair of graphite rods in the water, and a voltage divider circuit. As the water level rises, the current would travel through less graphite, and the resistance would drop. I don't know if that would give you enough top-to-bottom measuring distance.


body:
I am trying to use multiple PN532 reader. I have put all my readers on a multiplexer (TCA9548A).

The script works well, but when I move my tags on readers sometimes the serial says to me there is an error on reading tag like that : `Read failed [number]` or like `Error. Failed read page [number]` where [number] is a Integer.

And sometimes the serial completely hangs and not sends anything anymore, I have to reset the arduino by pressing the reset button.

## Other information :

Arduino : My arduino is a Mega.

Here is my code :

```
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

#define TCAADDR 0x70

#define RST_PIN 2

PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);

int NB_NFC_READER = 4;

void tcaselect(uint8_t i)
{
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

void setup(void)
{
    while (!Serial);
    delay(250);

    Wire.begin();

    // Serial.begin(115200);
    Serial.begin(9600);

    //Serial.println("NDEF Reader");

    /**Initialisation des lecteurs NFC*/
    for(int i = 0 ; i < NB_NFC_READER ; i++)
    {
      //Serial.println("CONFIGURATION DU READER N° " + String(i));
      tcaselect(i);
      nfc.begin();
    }

    pinMode(RST_PIN, INPUT);
    digitalWrite(RST_PIN, HIGH);

    Serial.println("SETUP OK !");
}

void loop(void)
{
  String tag0;
  String tag1;
  String tag2;
  String tag3;

    for(int i = 0 ; i < NB_NFC_READER ; i++)
    {
      //Serial.println("FOR INDEX : " + String(i));
      tcaselect(i);
      if (nfc.tagPresent(100))
      {
          NfcTag tag = nfc.read();
          //tag.print();
          if(i == 0)
          {
            tag0 = tag.getUidString();
          }
          if(i == 1)
          {
            tag1 = tag.getUidString();
          }
          if(i == 2)
          {
            tag2 = tag.getUidString();
          }
          if(i == 3)
          {
            tag3 = tag.getUidString();
          }
          //Serial.println("LECTURE SUR LECTEUR " + tag.getUidString());
          delay(100);
      }
    }
    Serial.print("[");
    Serial.print("{\"tag0\":");Serial.print("\"");Serial.print(tag0);Serial.print("\"},");
    Serial.print("{\"tag1\":");Serial.print("\"");Serial.print(tag1);Serial.print("\"},");
    Serial.print("{\"tag2\":");Serial.print("\"");Serial.print(tag2);Serial.print("\"},");
    Serial.print("{\"tag3\":");Serial.print("\"");Serial.print(tag3);Serial.print("\"}");
    Serial.println("]");
}
```

Thank you for reading, I hope someone will find why the serial freeze like that.

title: Serial Hangs with multiple PN532 nfc reader and a TCA9548A

Answers: 0


body:
I'm connecting to a MAX9611 on a custom PCB (using a SAMD Cortex M0 running an Adafruit Feather bootloader) using I2C. I have code that reads the voltage, current and temperature from the internal registers, but I'm receiving junk data from the voltage and current registers. Temperature works reliably.

Sometimes voltage and current are 0. Sometimes voltage is 10x what it should be (that's the raw ADC value - this isn't a conversion bug). The current reading depends on whether the temperature request is commented out or not.

I've been reading through the documentation for a day now and can't see what I'm doing wrong. The kicker is that the code to request the register data is essentially identical (just pointing at different registers) between the working temperature request and the non-working voltage and current requests. I have posted it below, along with the relevant schematic section - does anyone have any ideas what I'm doing wrong?

Thanks!

```
#include <Wire.h>

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

void loop()
{
  Serial.print("mV:   ");  Serial.println(get_MAX9611_voltage());
  Serial.print("mA:   ");  Serial.println(get_MAX9611_current());
  Serial.print("Temp: ");  Serial.println(get_MAX9611_temp());
  Serial.println();
  delay(1000);
}

uint16_t get_MAX9611_voltage (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x03);                             //Set mux to read from RS+
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x02);                             //Select RS+ data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read RS+ MSB
  uint8_t lsb = Wire.read();                    //Read RS+ LSB

  uint16_t MAX9611_voltage = word(msb,lsb);
  MAX9611_voltage = MAX9611_voltage >> 4;       //shift right by 4 due to 12 bit value
  MAX9611_voltage = MAX9611_voltage*14;       //57.3V full scale, 14mV per ADC step

  return MAX9611_voltage;
}

uint16_t get_MAX9611_current (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x02);                             //Set mux to read from current sense amplifier with gain 8x, full scale = 55mV
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x00);                             //Select CSA data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read CSA MSB
  uint8_t lsb = Wire.read();                    //Read CSA LSB

  uint16_t MAX9611_current = word(msb,lsb);

  MAX9611_current = MAX9611_current >> 4;       //shift right by 4 due to 12 bit value
  MAX9611_current = (MAX9611_current*0.01342)*5;  //ADC value in millivolts, I=V/R where R is 0.2

  return MAX9611_current;
}

int16_t get_MAX9611_temp (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x06);                             //Set mux to read from temp sensor
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x08);                             //Select temp data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read temp MSB
  uint8_t lsb = Wire.read();                    //Read temp LSB

  int16_t MAX9611_temp = word(msb,lsb);
  MAX9611_temp = (((MAX9611_temp >> 7) * 480)/1000);                     //shift right by 7 due to 9 bit value, LSB is 480mC

  return MAX9611_temp;
}
```
[![MAX9611 schematic][1]][1]

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

title: MAX9611/2 - receiving junk data

Answers: 1

body: That didn't take long to find the bug... Continuous read mode requires 2ms pause between each ADC read. I'm reading far faster than that, especially considering my micro is far faster than the 8 bit 328s that many other examples use. I added 2ms delay between reads and the problem seems to have disappeared, although I will have to check the current measurements when I have access to better equipment.