text:
Arduino Serial Monitor Input 3DES Encryption
I am trying to 3DES encryption using Serial Read, Found this 3DES Sample code in Github,
#include <DES.h>
DES des;
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");
}
void loop() {
  desTest();
  tdesTest();
  delay(2000);
}
void desTest()
{
  byte out[8];
  byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  byte key[] = { 0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e };

  Serial.println();
  Serial.println("========= DES test ==========");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.encrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.decrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
}
void tdesTest()
{
  byte out[8];
  byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  byte key[] = {
                  0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
                  0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
                  0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
                };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
}
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

I want to get user serial input from Serial Monitor to feed byte in[]. Which will encrypt user input, I will pad user input to 8 Bytes or restrict input to 8.
Library: https://github.com/Octoate/ArduinoDES
Could any one help me to get data from user input.
Edit 1: I was able to read the String to char and feed to byte in[] changed the code,
#include <DES.h>
DES des;

String  input;

char buf[30];
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");

}

void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}
void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    char buf[30];
/*
    input.toCharArray(buf, 9);
    Serial.println(buf);
*/
    input.toCharArray(buf, input.length() + 1);
    Serial.println(buf);

    byte out[8];
    byte in[] = {buf};
    Serial.println(buf);
    byte key[] = {
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
      0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
    };

    Serial.println();
    Serial.println("====== Triple-DES test ======");

    //encrypt
    Serial.print("Encrypt...");
    unsigned long time = micros();
    des.tripleEncrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);

    //decrypt
    for (int i = 0; i < 8; i++)
    {
      in[i] = out[i];
    }
    Serial.print("Decrypt...");
    time = micros();
    des.tripleDecrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);
    delay(2000);
  }

}

But I don't think getting the correct,
Please find the below,

But when I feed manually like below,
...
input.toCharArray(buf, input.length() + 1);
    Serial.println(buf);

    //tdesTest();
    byte out[8];
    byte in[] = {"12345678"}; //Manually feeding hardcoding the value need to get the value from serial read to here
    Serial.println(buf);
    byte key[] = {
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
      0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
    };

    Serial.println();
    Serial.println("====== Triple-DES test ======");
...

I get the expected output,

https://majenko.co.uk/blog/reading-serial-arduino

Hi @Majenko, Thanks for the reply,  I can read the serial string from while (Serial.available > 0) {
a = Serial.readString(); // read the incoming data as string

} But I could not find a way to feed it to the "byte in[ ]" in tdesTest Method due to unable to feed the string.

Well, that all depends on what format your input is in and what format you need to feed into the in array.

I want to input String from Serial and convert it to Char and feed to in[ ] @Majenko

Yes, I gathered that. But what is in the string, and how does that relate to what would be put into in[]?

String is the data needs to be encrypted which will be feeds to in [ ] for encryption using DES Library.

byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; will be replaced by Char in [] = {Data_from_SerialRead}

a.c_str() gives you a char * array pointer to the internal data buffer of the string. Is that what you are after?

@Majenko Thanks, Could you give me an example found this on internet but I have no idea how to use it.

From your comments I think I understand what you are after.  So, assuming you have read some string into a String object called input and you have an array in[8] to populate you can:

Clear the in[] array to a preset state
Copy the string content into in[]

As code:
memset(in, 0, 8); // Erase the contents of in[]
input.toCharArray((char *)in, 8); // Copy up to 8 bytes from the string

Comments are not for extended discussion; this conversation has been moved to chat.

#include <DES.h>
DES des;
byte in[8];
String  input;

char buf[30];
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");

}

void tdesTest() {
  byte out[8];

  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(2000);
}

void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string
    tdesTest();

  }
}


text:
Writing multiple inputs to serial port using a while loop
I am trying to get the serial monitor to prompt me to input two settings - the PWM level and the Resonance level. I am being prompted to input the PWM level, but before I can input the Resonance level it is set to zero and then I am asked again for the PWM level.
I am using Serial.flush(); inbetween the commands to clear the serial input, but I still cannot input the Resonance level before it is set to zero.
Here is my code:
int PWMPin = 10;       // Pin 10 connects to MOSFET gate on breadboard
int ResPin = 4;        // Pin for the resonator stage

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);   // Define baud rate for console to be 9600
  pinMode(PWMPin, OUTPUT);
  pinMode(ResPin, OUTPUT);

}

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

Serial.println("What PWM level do you want to test?");   // Testing only
 while (Serial.available() == 0) {
     // Wait for user input
  }
  int test_level_PWM = Serial.parseInt();
    analogWrite(PWMPin, test_level_PWM);
    Serial.print("PWM Level: ");
    Serial.println(test_level_PWM);

Serial.flush();

Serial.println("What Resonance level do you want to test?");
 while (Serial.available() == 0) {
     // Wait for user input
  }
  int test_level = Serial.parseInt();
    analogWrite(ResPin, test_level);
    Serial.print("Resonance Level: ");
    Serial.println(test_level);

   delay(1000);

Here is the serial monitor output. I was able to input the PWM level but the Resonance level was set to zero immediately after and then I was asked to input the PWM level again.

I would consider restructuring this into a state machine with (something like) "input" and "run" states. I'd also reconsider using parseInt because its default timeout of 1s can lead to unexpected behavior; might just want to handle that manually.

Serial.flush() doesn't do what you think. the line end characters will be still in the RX buffer. flush() waits for TX buffer to be send. https://www.arduino.cc/reference/en/language/functions/communication/serial/flush/

in the serial monitor, in place of new line ending, select no line ending. After making this change, your code worked on my system.

Your line
   Serial.flush();
is probably intended to remove additional input after the expected numerical input. But that's not what it's doing. (See @jurai's comment)
Either avoid additional input like NewLine characters, or remove them using something like
while (Serial.available()) {delay(1); Serial.read();}
( The delay(1); takes care of slowly coming in serial data at 9600 Baud )

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
esp8266 analogRead of 5.5V soil moisture sensor input using voltage divider
On an ESP8266 I try to analogRead(A0) my soil moisture sensor using a voltage divider but I get unexpected low values.
The MT3608 increases the esp's output voltage from 3.3V to 5.5V which is the recommended voltage for my capacitive soil moisture sensor v1.2 (different to the picture below I use v1.2, not v1.0). When there is no voltage divider in the game and the sensor is dry, the sensor outputs ~4.5V (yellow wire). The output is around ~2.3V when the sensor is completely wet.
For my voltage divider I use a 150 Ohm (R1) and a 39 Ohm (R2) resistor. Given ~4.5V Vin on the yellow wire this should provide me with ~0.9V Vout on the green wire, because Vout=Vin*(R2/(R1+R2)). A voltage <=1V I could safely attach to the esp8266 A0 analog pin. However, using the voltage devider I measure only 8,3mV instead of the expected 0.9V! It drops to 7.7mV when Vin is 2.3V (wet sensor).

What am I doing wrong? Any advise is highly appreciated!
For testing I currently use a board which has a build-in internal voltage divider that allows for up to 3.3V input, however in the final design I need to run everything using an ESP12-E without such an internal divider.

If the "V3" is anything like the "V1" then the A0 pin already has a voltage divider in it aimed at 3.3V operation (the analog input of the ESP8266 only handles 1.1V max). You just need to add another resistor instead of a whole voltage divider to adjust the onboard one. 100kΩ should work.

It looks like my board has a voltage divider on it, however I use the NodeMCU board just for testing and need to run the final circuit with an ESP12-e that doesn't have a build-in voltage divider and expects <=1V analog input. I still wonder why I get this low value of just 8.3mV while I actually expect 900mV

Just use the internal divider as part of your design.

but ESP12-e doesn't have an internal divider, it's just the chip. I edit the question to make this more clear.

Neither does the esp that is on the nodemcu. The divider is on the board. That is most of your divider that you want to design. When you go to your own design of board just take that but of divider design with you.

those resistors are way too low of a value; they are pulling down the output. Multiply your ohms by 100 and it should work.

@dandavis, thank you that did the trick! I'm curious, can you provide me with an explanation why a voltage divider with more Ohms result in higher Vout?

A low-resistance voltage divider draws more current than a high resistance one, even without a measurement device (your ESP) connected at the mid-point. The power supply must be able to supply enough current and still maintain it's voltage. If it isn't, the supply voltage drops.

@mika Look this exemple using ampOps.

I got similar situation having a 47ohm as R2, the one that goes to ground, how did you fix the issue? After reading the comments of Vincent and @dandavis , I patched the R2 adding a 10Kohm in serial having a total of 10047ohm now and suddenly the levels detected in the analog pin rose. When I have a 100K in the cable to the analog pin, with 47ohm I was getting 13 similar to when no data was coming, having 47K I was getting 13~14, with 10047ohm in R2, the value of the analog pin jumped to 108 for 100K and 195~196 for 47K.

When designing a voltage divider with 2 resistors, there are 2 things to consider:

The ratio between R1 and R2, which gives the output voltage: U(out) = U(in) * [R2 / (R1 + R2)]
The magnitude of each resistors: to get a 1/2 ratio, you need to have R1 = R2 no matter their value. But depending the value of your resistors (it can be 10Ω, 1kΩ, 100kΩ or 10MΩ for example), you will have a different current travelling through the bridge. The higher the resistors, the lower the current, and vice-versa.

When mesuring voltage inside the voltage divider, the ADC can be considered as a load to the circuit (as shown below). Some forums state that the input resistor of the ESP8266 ADC is around 20MΩ. If the resistors of the bridge are too low, the current will be high and will only travel through the bridge, leaving not enough current for the ADC to measure (electrons are lazy and always take the path of least resistance). On the other hand, if the resistors are too high, the current will be to low to be accurately detected as well.

In most cases, voltage dividers are build with resistors between 10kΩ and 1MΩ. This allows enough current to travel through the ADC to give an accurate measure of the voltage.
As suggested by dandavis comment, choosing (R1 ; R2) = (15kΩ ; 3,9kΩ) or (150kΩ ; 39kΩ) should work in your circuit.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Avoid using delay with the HR-S04 ultrasonic sensor
How can I measure the distance of an HR-S04 ultrasonic sensor with millis and micros?

I'd use the Input Capture ability of Timer1, but that's beyond the scope of this site - maybe you can find a library that does that for you.

@Majenko, did you see the self-answer?

@Juraj I did. Looks fine to me.

@Majenko, most ultrasonic code I saw activated trig for some microseconds and then used pulseIn to catch the echo. but the code in answer triggers for 10 milliseconds using states

The falling edge is what matters. It still uses pulseIn.

In response to @Majenko comment on the original question, here is some code that I use which uses the Timer1 input capture function to read an ultrasonic sensor.  It also uses the Timer1 PWM generator to create the trigger pulses.  The entire code is interrupt driven and nothing blocks the main program.
It's not built as an official style library with all the extra parts, but the .h and .cpp can be put into a folder in the libraries folder as in the manual installation process.  It's really just a personal library that I use on some of my robots, but I'm happy to share.
The code as written supports the ATMEGA1284P and ATMEGA328P chips.  There are a couple of lines to comment and un-comment to change between the two.
It exposes a singleton instance much like the Serial class, so there's nothing to instantiate.  The pins are all set by hardware, you can't change them.
Depending on how much total range you want, you can set the prescaler to a much lower value.  If you run with no prescaler then the resolution would be something on the order of nearly 100 times what you can get with micros (62.5ns vs 4us resolution).  But that would be shorter distances like 1.2m and less.
https://github.com/delta-G/PingTimer
#include "PingTimer.h"

int distance;

void setup() {

  Serial.begin(9600);
  ping.begin();
  ping.sendPing();

}

void loop() {

  //  if the ping sensor has new data save it to distance and print it.
  if(ping.hasNewData()){
    distance = ping.getDistanceMM();
    Serial.print("Current Distance: ");
    Serial.println(distance);
    ping.sendPing();
  }

  //  Do other things not blocked by ping sensor

}

PingTimer.h
/*

PingTimer  --  uses Timer1 Input Capture to read a HC-SR04
     Copyright (C) 2019  David C.

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     */

#ifndef PINGTIMER_H_
#define PINGTIMER_H_

#include "Arduino.h"

// Ping pin on OC1A -- PB1 on 328P.  (UNO pin 9)
                    //-- PD5 on 1284P  (pin 13)
#define PING_PIN_MASK (1 << 5)
#define PING_PIN_PORT PORTD

// Echo pin on ICP1 -- PB0 on 328P  (UNO pin 8)
                    //-- PD6 on 1284P  (pin 14)
#define ECHO_PIN_MASK (1 << 6)
#define ECHO_PIN_PORT PIND

class PingTimer {
private:
    volatile uint16_t timerVal;
    volatile boolean overflowed;
    volatile boolean newData;

    void initTimer();

    void startPulse();

public:
    PingTimer();
    void begin();

    void sendPing();
    void echoHandler();
    void overflowHandler();

    boolean hasNewData();
    boolean hasOverflowed();
    uint16_t getTimerVal();

    int16_t getDistanceMM();

};

extern PingTimer ping;

#endif /* PINGTIMER_H_ */

And the PingTimer.cpp
/*

PingTimer  --  uses Timer1 Input Capture to read a HC-SR04
     Copyright (C) 2019  David C.

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     */

#include "PingTimer.h"

PingTimer ping;

PingTimer::PingTimer(){
    newData = false;
    overflowed = false;
    timerVal = 0;
}

void PingTimer::begin() {
    initTimer();
    // ATMEGA328P
//  pinMode(8, INPUT);
//  pinMode(9, OUTPUT);
    // ATMEGA1284P
    pinMode(14, INPUT);
    pinMode(13, OUTPUT);
}

void PingTimer::initTimer(){
    cli();
    TCCR1A = 0;  // no PWM
    // Noise Cancel On, RISING Edge , No prescaler, 4ms range.
    TCCR1B |= ((1 << ICNC1) | (1 << ICES1) | (1 << CS11) | (0 << CS10));
    // make sure analog comparator isn't selected as capture input
    ACSR &= ~(1 << ACIC);
    //  Turn off Timer interrupts
    TIMSK1 = 0;
    // setup COMPA for 10us to time the trigger pulse
    // and COMPB for 12ms for out of range signal (a little over 4 meters)
    OCR1AH = 0;
    OCR1AL = 20;  // With prescaler at 8 each tick is 0.5 us.
    OCR1BH = 0xB5;
    OCR1BL = 0xB0; // 0xB5B0 is 46512.  That's a little over 4 meters with prescaler at 8.
    sei();
}

//  This is a public facing function to call the startPulse so it can stay private
//  since it twiddles registers
void PingTimer::sendPing() {
    startPulse();
}

void PingTimer::startPulse(){
    // set pin high and setup PWM unit to
    // turn the pin off 10us later
    cli();
    TCNT1H = 0x00;
    TCNT1L = 0x00;
    //Set up to get one pulse of PWM
    // Clear OC1A on compare match.  10bit fast PWM
    TCCR1A = ((1 << COM1A1) | (1 << WGM11) | (1 << WGM10));
    // Setup input capture interrupt to catch the rising
    // of the echo pin and start the timer
    // Noise Cancel On, RISING Edge ,prescaler at 8 gives a 32ms timer = 5.5 meter range
    TCCR1B = ((1 << ICNC1) | (1 << ICES1) | (1 << CS11) | (0 << CS10) | (1 << WGM12));
    //  Turn on interrupt Input Capture
    TIFR1 = ((1 << ICF1) | (1 << TOV1));
    TIMSK1 = ((1 << ICIE1));
    overflowed = false;
    newData = false;
    sei();
}

// Called from ISR
void PingTimer::echoHandler() {
    if (ECHO_PIN_PORT & ECHO_PIN_MASK) {  //Rising Pin
        // Kill the OC1A PWM unit and return to normal mode
        TCCR1A = 0;
        // Noise Cancel On, FALLING Edge ,prescaler at 8 gives a 32ms timer = 5.5 meter range
        TCCR1B = (1 << ICNC1) | (0 << ICES1) | (1 << CS11) | (0 << CS10);
        // Reset Timer1
        TCNT1H = 0;
        TCNT1L = 0;
        //  Reset Input Capture and Timer Overflow Interrupts
        TIFR1 = (1 << ICF1) | (1 << TOV1);
        //  Turn on interrupts Input Capture and Timer Overflow
        TIMSK1 = (1 << ICIE1) | (1 << TOIE1);
    } else {  // Falling pin
        // Read the ICR1 Register
        uint8_t low = ICR1L;
        uint8_t high = ICR1H;
        timerVal = ((high << 8) | low) - 4; // Noise canceler adds 4 clock cycles

        //  turn off the timer interrupts
        TIMSK1 = 0;
        newData = true;
    }
}

// Called from ISR  Timer 1 OVF
void PingTimer::overflowHandler(){
    //turn off timer interrupts
    TIMSK1 = 0;
    newData = true;
    overflowed = true;
}

boolean PingTimer::hasNewData(){
    cli();
    boolean retval = newData;
    newData = false;
    sei();

    return retval;
}

boolean PingTimer::hasOverflowed(){
    cli();
    boolean retval = overflowed;
    overflowed = false;
    sei();

    return retval;
}

uint16_t PingTimer::getTimerVal() {
    uint16_t retval = 0;
    cli();
    if (overflowed) {
        retval = -1;
    } else {
        uint16_t copy = timerVal;
        retval = copy;
    }
    sei();
    return retval;
}

int16_t PingTimer::getDistanceMM() {

    int16_t retval = 0;
    uint16_t copy = getTimerVal();
    if (copy == (uint16_t) -1) {
        retval = -1;
    } else {
        // 16Mhz is 62.5 ns/clock
        // We've got the prescaler dividing by 8
        uint32_t nanoSecs = copy * 62.5 * 8;
        //speed of sound in mm/ns
        uint16_t mm = nanoSecs * 0.000344;
        retval = mm / 2;  // half a round trip
    }
    return retval;
}

ISR(TIMER1_CAPT_vect){
    ping.echoHandler();
}

ISR(TIMER1_OVF_vect){
    ping.overflowHandler();
}

ISR(TIMER1_COMPB_vect){
    ping.overflowHandler();
}

Many years ago, it was recommended to access 16-bit I/O registers one byte at a time, reading LSB-first and writing MSB-first. This is ancient history. As gcc has since learned how to access those registers, you can now simply write OCR1B = 46512 and timerVal = ICR1.

I think I sorta knew that and wasn't sure I remembered right so I just went with what the datasheet said to do.  If I update this later I'll add that change.

I have noticed that many people on the net have problems using millis with the sensor to take measurements etc. so I created this sketch to help anyone.
You are free to ask for any clarification about it!
/*
 *  HC-SR04 sensor measuring
 *
 *  Non-blocking HC-SR04 sensor measuring
 *
 *  The circuit:
 *  - Echo pin connected to pin 2
 *  - Trigger pin connected to pin 3
 *  - VCC pin connected to VCC (5v)
 *  - GND gger pin connected to GND
 *
 *  created 3 Jul 2021
 *  by alessandromrc
 */

#define trigPin 3
#define echoPin 2

unsigned long timerStart = 0;
unsigned long StartTime = micros();
bool timer = false;
const unsigned long HIGH_TRIGGER = 10;
const unsigned long LOW_TRIGGER = 2;

float timeDuration, distance;

enum SensorStatus {
  TRIG_LOW,
  TRIG_HIGH,
  ECHO_HIGH
};

SensorStatus sensorStatus = TRIG_LOW;

bool isTimerReady(const unsigned long Sec) {
  return (micros() - timerStart) < Sec;
}

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

void loop(void) {
  switch (sensorStatus) {
  case TRIG_LOW: {
    digitalWrite(trigPin, LOW);
    timerStart = micros();
    if (isTimerReady(LOW_TRIGGER)) {
      sensorStatus = TRIG_HIGH;
    }
  }
  break;

  case TRIG_HIGH: {
    digitalWrite(trigPin, HIGH);
    timerStart = micros();
    if (isTimerReady(HIGH_TRIGGER)) {
      sensorStatus = ECHO_HIGH;
    }
  }
  break;

  case ECHO_HIGH: {
    if (!timer) {
      Serial.print("Microseconds Passed in initialization: ");
      Serial.println(micros() - StartTime);
      timer = !timer;
      Serial.println("Starting to Measure");
    }
    digitalWrite(trigPin, LOW);
    timeDuration = pulseIn(echoPin, HIGH);
    Serial.print("Measured: ");
    Serial.print(timeDuration * 0.034 / 2);
    Serial.println(" cm");
    sensorStatus = TRIG_LOW;
  }
  break;
  }
}

Github Repository

it is enough to trigger for 5 microseconds. why do you use a separate state to trigger for 10 milliseconds?

@Juraj I didn't knew about this, thanks for letting me know!


text:
DHT11 humidity and temperature sensor
Hello. I've got a question about DHT11 sensor. Why should pullup resistor be connected as on the image below:

while as far as I know, pullup resistor should be placed between Arduino 5V pin and Vcc of sensor as shown here:

PS: I know that there is a wrong icon of DHT11, but I couldn't find a correct one.

I don't know why but the datasheet says dataline must be connected to 4.7K pullup
http://robocraft.ru/files/datasheet/DHT11.pdf

Then it wouldn't be a pull-up resistor; Vcc already is 5V. Signals are what need to be pulled high or kow.

@Dave Newton but it seems to me, that when the resistor is connected as shown in the first image, it's in parallel to Vcc-OUT in sensor therefore resistance between 5V and OUT is 0.

If you draw a proper schematic, you will see that, in the first drawing, the resistor is between Vcc and Out (also called “data”). It “pulls up” the data/Out pin to a high logic level when there’s no internal or external signal driving it.

You require a pullup resistor between the data wire and VCC because the DHT11 uses a bidirectional communication system on a single wire.  When neither end is communicating both ends of the link will be in "high impedance" mode - i.e., input mode. In that case the signal will be "floating" and needs the pullup to keep it in a known state.
When actively communicating the outputs switch to "open drain" mode to allow then to pull the signal low against the pull of the pullup resistor.
A resistor in series with the Arduino's 5V and the VCC of the DHT11 is not a pullup resistor. It is not an arrangement that you would ever want, since it would make the voltage to the DHT11 unstable.

Note that the pullup is typically not required when using one of the common breakout boards for DHT11 (from Adafruit or similar), because they already include it.


text:
Pass Byte Array to Char and Send to a Separate Arduino
I am trying to send data between Arduino Nano and D1 Mini (ESP 8266 Module)
My Code as below in Nano which will be the transmeting ,
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;
char text[20];
char charVal[6];

char buf[30];
void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");

}

void tdesTest() {
  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  /*
    //decrypt
    for (int i = 0; i < 8; i++)
    {
      in[i] = out[i];
    }
    Serial.print("Decrypt...");
    time = micros();
    des.tripleDecrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);
    delay(2000);
  */
}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();

}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string
    tdesTest();

  }
}

In printArray(byte output[])I am getting Output as HEX Byte as below

I am trying to send the this encrypted data to from Arduino nano to D1 Mini,
I have wrote a small Receiver  Application in D1 Mini and It works ,
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
char cString[2000];
byte chPos = 0;
byte ch = 0;
char dataStr[6];

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available())
  {
    ESP.wdtDisable();

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }

  cString[chPos] = 0; //terminate cString
  chPos = 0;

  Serial.print(cString);
  ESP.wdtEnable(1);
  Serial.flush();

}

I want to pass this HEX data Generated to D1 Mini from Arduino Nano,
I have wrote test code in Arduino Nano for Transmitter(Nano) and between Receiver (D1 Mini) it works,
//Transmitter Code for Testing Connections
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
byte greenLED = 12;
char text[20] ;
char charVal[6];

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

}

void loop()
{
  strcat(text, "Message"); //append to empty string
  Serial.println(text); //print to local screen for debug*
  link.println(text);

  delay(10000);
}

Please help me to send this HEX data in single shot to D1 Mini.

You can change your printArray function to work on provided Print instance:
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      serial.print("0");
    }
    serial.print(output[i], HEX);
    serial.print(" ");
  }
  serial.println();

}

then you can use it as printArray(out, Serial); or printArray(out, link);.

Thanks for the comment, I have applied your solution like this: link and getting this error link

Please help me to correct it if it's a wrong way I am using

Could you elaborate please ?

Could you show it in the code ?

Thanks, Got it. But Receiver not showing any output. I think this will pass the HEX output as it is, But receiver is expecting Char input.  Any idea how to make it char printArray(out, link);

byte is char, char is byte. you can do link.write(out, 8);

Thanks it worked , But what I am receiving is unreadable link

of course it is unreadable. it is the same array for which you use your printArray to print it.

Could you advise how to make it readable ?

use your printArray function

I have add it as this Code but getting error Error

Could you help me to fix this

No worries, I was bale to fix it.

Thanks for the support, really  appreciated.

Let us continue this discussion in chat.


text:
Artefacts on display when adding seemingly unrelated code
I have this simple program, where I am implementing a menu structure on an OLED display and a rotary encoder.
The code works functionally as intended, however when I add more menu items, then I get some artefacts on the display, in the lower right corner (see screenshots).
The code that I am referring to is inside the block comment in initMenu().
When I uncomment that block, the artefacts start appearing, every other time I turn the knob on the encoder. Sometimes it temporarily disappears, or slightly changes its shape.

As I said, other than that, the code behaves as expected.
Could anyone maybe shed some light on why this happens?
#define DEBUG 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = "Auto";
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = "Manual";
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = "Config";
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;
/*
  peakAverage.name = "PAvg";
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = "P2P";
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = "RMS";
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
*/
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print("Hello");
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      printMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      printMenu();
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println("clockwise");
#endif
    currentItem = currentItem->nextSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println("counterclockwise");
#endif
    currentItem = currentItem->prevSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println("no rotation");
#endif
    // ?
  }
}

void printMenu() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.clearDisplay();
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  int x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  int x2 = 64 - currentItem->name.length() * 6;
  int width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  int x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
  display.display();
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}

This is the output of the compilation process regarding program size:
Sketch uses 18198 bytes (59%) of program storage space. Maximum is 30720 bytes.
Global variables use 827 bytes (40%) of dynamic memory, leaving 1221 bytes for local variables. Maximum is 2048 bytes.

(4 <= currentItem->id <= 6) is parsed as ((4 <= currentItem->id) <= 6) which is always true since comparisons evaluate to 0 or 1. You need to split it up ((4 <= currentItem->id) && (currentItem->id <= 6)).

How much free RAM do you have?

Looks like your stack is ramming into your heap.

@EdgarBonet I updated my question regarding size. Would it help to split printMenu into smaller chunks? Put all constant Strings to PROGMEM?

Thanks for the comments about memory usage, I was able to solve this specific problem.
I have updated my program, and optimized it by splitting up the menu rendering, using smaller variable sizes where possible, and putting all Strings to PROGMEM using the F() macro.
I also had a look at this page https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory and copied freeMemory() from there:
#define DEBUG 1
#define DEBUG_MEMORY 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

#ifdef DEBUG_MEMORY
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}
#endif

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = F("Auto");
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = F("Manual");
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = F("Config");
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;

  peakAverage.name = F("PAvg");
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = F("P2P");
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = F("RMS");
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print(F("Hello"));
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      renderMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      renderMenu();
      #ifdef DEBUG_MEMORY
        Serial.println(freeMemory());
      #endif
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("cw"));
#endif
    currentItem = currentItem->nextSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("ccw"));
#endif
    currentItem = currentItem->prevSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println(F("nr"));
#endif
    // ?
  }
}

void renderMenu() {
  display.clearDisplay();
  printPrevSibling();
  printCurrentItem();
  printNextSibling();
#ifdef DEBUG_MEMORY
  Serial.println(freeMemory());
#endif
  display.display();
}

void printPrevSibling() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  byte x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
}

void printCurrentItem() {
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  byte x2 = 64 - currentItem->name.length() * 6;
  byte width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
}

void printNextSibling() {
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  byte x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}

Now the size is like this:
Sketch uses 18588 bytes (60%) of program storage space. Maximum is 30720 bytes.
Global variables use 761 bytes (37%) of dynamic memory, leaving 1287 bytes for local variables. Maximum is 2048 bytes.

However the improvement is not that great, and I am still left wondering, when the next problem will arise. I am still thankful for further insights besides using a bigger controller, because I am not quite done yet on this one.
If anyone has more ways for me to improve this program without sacrificing performance, as I will be adding a radio, and a microphone, I will accept that as an answer over this one.

Does repeatedly printing the free memory show something suspicious? You have quite a bit of RAM left and you don't seem to have an recursive code, so I wonder where the memory would overflow. I also see no dynamic memory allocations.

@PMF: the Adafruit SSD1306 library mallocs 1k of RAM in this configuration for a screen buffer. Makes it very convenient but barely usable on a Uno. There are probably better libraries if all that is needed is printing some text.

@PMF Yes, as @Mat pointed out, instantiating the display object eats a lot of RAM at once. I eventually resorted to using lower SCREEN_WIDTH and SCREEN_HEIGHT...


text:
Sending Data Between Arduino Nano and D1 Mini
I am sending data from Arduino Nano to D1 Mini,
Transmitter is Arduino Nano
Transmitter Code:
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;
char text[20];
char charVal[6];
char buf[30];
void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");
}
void tdesTest() {
  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };
  Serial.println();
  Serial.println("====== Triple-DES test ======");
  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  delay(10000);
  printArray(out, link);
  link.write(out, 9);
  delay(2000);
  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(2000);
}
//passing output and Print
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);
  }

  Serial.println();
}
//printing output without link pass
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);
  }
  Serial.println();
}
void userdata() {
  Serial.println("Sending User Data");
  byte user[] = {0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30};
  printArray(user, link);
  link.write(user, 9);
  delay(100);
  tdesTest();

}
void loop() {
  while (Serial.available() > 0) {
    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

    userdata();
  }
}

And receiving same from D1 Mini (ESP8266)
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
byte cString[8];
byte chPos;
byte ch;
byte out[8];
String hexstring = "";

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available() > 0)
  {
    ESP.wdtDisable(); // This helps th avoid not reciving data after second try

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }
  if (ch != 0)
  {
    printArray(cString);
    ESP.wdtEnable(1);
    Serial.flush();
    cString[chPos] = 0; //terminate cString
    chPos = 0;
  }

}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    hexstring += String(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();
  Serial.println("Your String Sir:");
  Serial.print(hexstring);
  Serial.println();
  ch = 0; // Avoid printing 0s when no data is recived
  hexstring = ""; //Clear the memeory of hexstring
}

In Receiver I am receiving data as below:

I want to get data in Single Stream to receiver as Example: 31 30 30 30 30 30 30 30 7E B5 2D 4D 93 CB 08 BA or in receiver join two streams in to a single stream,
On Side Note:
1st Part is Plain Data and 2nd Part will be Encrypted Data
Could anyone please help..

Can't you concat 2 strings? If you would a white space between each byte just concatenate a space. Trivial answer but I'm not sure which your core question is.

How to do that? Transmitter sends two char streams,

Since I don't think concat will work

Why not? You calculate hexstring, which can be concat to the next one.

Could you share me how in my receiver code ?

@fabianoriccardi Still Same Could you help me to fix the issue.

Accidently got deleted previous comment

Actually I don't know how to help you: I can explain what you should do, but I will not write code since I cannot test it.

Yes, Please help me, I will test it.

Managed Get it Working:
Change the Transmitter Code to Cascade Two Char Streams Before Sending:
Transmitter Code:
#include <DES.h>
#include <SoftwareSerial.h>
SoftwareSerial link(2, 3); // Rx, Tx
DES des;
byte in[8];
String  input;

void setup() {
  link.begin(9600);
  Serial.begin(9600);
  Serial.println("Hello! Pleace Enter Your Data to Encrypt");

}

//passing output and Print
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");

    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }

  Serial.println();

}
//printing output without link pass
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");

    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();
}

void userdata_and_Encrypt() {
  Serial.println("Sending User Data");
  byte username[] = {0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
  printArray(username, link);
  byte username_data = (username, 9);
  delay(100);

  byte out[8];
  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");
  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  delay(100);
  printArray(out, link);
  byte password_data = (out, 9);
  delay(100);
  byte data_stream = username_data + password_data;
  printArray(data_stream, link);
  link.write(out, 17);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(100);

}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

    userdata_and_Encrypt();

  }
}

Receiver Code to Accept 16 Bytes
Receiver Code:
//Receiver code
#include <SoftwareSerial.h>
SoftwareSerial link(4, 0); // Rx, Tx

byte greenLED = 13;
byte cString[8];
byte chPos;
byte ch;
byte out[8];
String hexstring = "";
static String data = "";

void setup()
{
  link.begin(9600); //setup software serial
  Serial.begin(9600);    //setup serial monitor
  pinMode(greenLED, OUTPUT);
}

void loop()
{

  while (link.available() > 0)
  {
    ESP.wdtDisable(); // This helps th avoid not reciving data after second try

    //read incoming char by char:
    ch = link.read();
    cString[chPos] = ch;
    chPos++;

    digitalWrite(greenLED, HIGH); //flash led to show data is arriving
    delay(20);
    digitalWrite(greenLED, LOW);

  }
  if (ch != 0)
  {
    printArray(cString);
    ESP.wdtEnable(1);
    Serial.flush();
    cString[chPos] = 0; //terminate cString
    chPos = 0;
  }

}

//printing output
void printArray(byte output[])
{
  for (int i = 0; i < 16; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    hexstring += String(output[i], HEX);
    Serial.print(" ");
    delay(100);

  }
  Serial.println();

  Serial.println("Your String Sir:");
  Serial.println(hexstring);

  Serial.println();
  ch = 0; // Avoid printing 0s when no data is recived
  hexstring = ""; //Clear the memeory of hexstring
}

Working Output:


text:
How to run a sketch for a period (e.g. 1min) and then attiny85 goes to sleepmode automaticaly?
Another beginner to arduino device.
My knowledge for programming is so weak.
As i mention to the title i would like your help.
I just want to run this simple sketch into attiny85 for lets say 1 min and then chip goes to sleepmode by its own.
My code is below but i cannot manage to achive what i want.
Any help?
Many thanks.
void setup() {

  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);

}

void loop() {

                              // put your main code here, to run repeatedly:
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);

  digitalWrite(0, HIGH);
  digitalWrite(1, LOW);  // 1
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, HIGH);   // 2
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);      //3
  digitalWrite(2, HIGH);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //4
  digitalWrite(2, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //5
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //4
  digitalWrite(2, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);     //3
  digitalWrite(2, HIGH);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, HIGH);   // 2
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, HIGH);
  digitalWrite(1, LOW);  // 1
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);

}

I'd start by turning your sets of five digitalWrite into a call to single function that takes the number given in the comment.

where is your attempt to put the device to sleep? ... you presented only unrelated code ... please present minimal code that demonstrates the problem ... that means, have code for only one LED

Hello,thanks both for your replies. This is my main sketch code. No attempt to put chip in sleepmode yet. Then its better to read more about commands, try to put attiny to sleepmode and revert. Maybe its to early for questions. thnx guys.

@GEORGEBOULIS I think that I have seen several tutorials about ATTiny85 sleep modes ... perhaps that can be your start

Thanks once again.

You can write, at the end of loop(), “if one minute has elapsed, then
go to sleep”. In C++, that would be:
if (millis() >= 60000)  // 60 seconds elapsed
    sleep_mode();

You will need to include <avr/sleep.h> in order to have access to the
sleep_mode() function. The sleep is likely to be very short though,
probably less than a millisecond, as the ATtiny will be waken up by the
next timer interrupt.
If you want a deeper, longer sleep, you could choose a different sleep
mode in setup():
set_sleep_mode(SLEEP_MODE_PWR_DOWN);

Read the datasheet if you want to know what wakeup sources are available
in each sleep mode.
Alternatively, if you want to make the ATtiny sleep forever (until the
next power cycle), call cli() in order to disable the interrupts,
right before calling sleep_mode().

Dear Edgar , i am trying to do whats u r saying and i have a good result. Sketch is running for a period set into millis() and then stops. The problem is that led in pinmode 0 remains high for ever. Now i am trying to figure out what i am doing wrong. Normally i desire all pinmodes to be low once sleepmode is activated. i will revert. Thanks again.

hELLO, i think i solved it. It was easier than i thought. After millis command I set all pinmodes to low digitalWrite(0, HIGH);
digitalWrite(0, LOW);
digitalWrite(1, LOW);  // 1
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);   after that statement i proceed with sleepmode commands and here we go. All leds stop flashing and no current runs from battery. This is a small victory for me. Thank you so much all.


text:
using pmrpcm library for sound output from Teensy3.2
I converted an MP3 sound effect (5 seconds long) to WAV to play it out of a Teensy3.2 with speaker connected to PWM output pin.  The TMRPCM library specifically talks about Arduino AVR boards, but doesn't mention Teensy.  On the PJRB (Teensy) website, the only info I can get is for their high quality audio shield with extensive programming.  I just want to play the simple WAV file from the SD card where it is located.  (I can display images on a GLCD from SD card, so not a problem).  The problem is when I compile my sketch I get many errors related ONLY to the the library.  If I don't include the TMRPCM library, there are no errors.  I DON'T NEED high quality sound!  Any ideas?  Another library perhaps, or tweaks to existing?  I can post the errors if necessary, they seem to be related to timers not being declared in the .h file.

Teensy 3.2 is not AVR Arduino. TMRPCM is only for AVR Arduino. Since the Teensy 3.2 has high quality sound why would someone port the low quality TMRPCM library to it? You could, but a simpler method is just to use a timer for sample rate and adjust PWM duty cycle per sample with a carrier frequency > 2x the maximum sample frequency.

Sometimes you don't need the expensive fountain pen...just a pencil.   The Teensy should do EVERYTHING and more than an AVR chip, in my opinion.  having said that, I'm using an el-cheapo ISD1820 sound module with small amplifier module and getting exactly the results I want.   I had been hoping to put a number of sound bytes on SD card, but this works and modules are so cheap I can use more than one.   Get 20 seconds of sound.

The Teensy can do everything the AVR Arduinos can, and more. It's just a SMOP. No one has needed it to do what you want, since it does better than what you want, so no one has bothered to program it yet.

I understand but I wanted to use TRMPCM to have a library of MP3/WAV SFX on an SD card.  Surely others would want such a thing, it would be great for games for example.  Another analogy: I wanted a small transistor radio, not a complete component stereo system.

So why use a Porsche to go shopping?


text:
Arduino 5v pin outputting lower power than expected
I have hooked the pin v5 of an Arduino Nano 33 BLE to the A0 pin and measured the value by doing Serial.println(analogRead(A0));. I would expect to see 1023 however instead I see the value oscillating around 810.
Any ideas why I am not getting 1023?
P.S.: I am powering the Arduino board through the USB connector.

You should probably stop doing that until you have an answer.

use a voltmeter

it is not lower power ... it is lower voltage ... the two are not the same thing

I hope you didn't  solder the 5 V pin pads on the bottom side of the board. the 5 V pins is not connected to not make 5 V circuits just like you did. because the input pins on this board are for 3.3 V max. https://www.arduino.cc/en/Guide/NANO33BLE#please-read

@Juraj I have soldered the 5v pin, because my sensors both require 5v. I have a Beetle Bluno BLE board that outputs 5v, I don't really understand the limitation. How am I supposed to power the sensors, with an extra external 5v power source?

and why do you wire 5 V to A0?

Because I don't have a voltmeter, so that was the only way for me to see what value was coming out from the 5v pin

With a divider it should be an okay way to measure.  If you connect A0 to your 3.3V pin, do you not see 1023 (or so) then?

Yes I see around 1023 if I connect A0 to my 3.3V pin

Well, that's the last thing I could think to ask that could disconfirm what I think is going on.  If I think of anything else, I'll ask.

Well, I thought by now someone else would have answered it.  But, I'll try.  I'm not familiar with this chip and board, so what I can tell you is pretty limited.
In short, you have a 3.3V micro-controller and generally speaking you don't hook 5V signals to them.  There are some 3.3V parts that have "5V tolerant" inputs, but that only makes sense for digital inputs so far as I know.
Barring anything unpleasant happening, the behaviour I would expect to see with hooking 5V to the input of a 3.3V ADC is that it would clip at the high end value.  So yeah, for 10-bit resolution, which appears to be the default for the Nano 33 BLE and with VDD as the reference, which also appears to be the default, I would expect to see a value at or near 1023.  Up until the point that you fry something that is.
I don't know why you're seeing lower values, but since you seem to be operating it out of specifications, I'm not sure that really matters why.  If you want to measure 5V with your 3.3V max ADC, you should involve a voltage divider.

the 5 V pin is not connected from factory on this board

Again, I don't know what you're talking about.  If you have an answer, post it as an answer.

https://www.arduino.cc/en/Guide/NANO33BLE#please-read

It's nice that they have an official warning about it.  The O.P. seems to remain unconvinced, for what reason I don't know.


text:
How to difference hardware reset and software reset?
I have an arduino code with an SD card where I save some data. When I load a new code, The SD must update with the new data that I put in the code, but if I reset the Arduino by the reset button, I don´t want the SD data to change.
To sum up, I want to reload SD data only when I update the code, and not with hardware reset
Any ideas?

Which Arduino do you have?

I´m trying with Arduino Uno, but the code should work for Nano and Mega too

Then I'm sorry, you can't. There is no "software reset". Uploading code triggers a hardware reset through "pressing" the reset for you.

Ah, so there isn´t real difference between both reset

You can't. There is no "software" reset. When you upload new code a hardware reset is triggered by the DTR pin of the USB interface chip.
Instead I would suggest maintaining a "data version number" on the SD card. Read it on startup and, if it differs from the expected version number (which you update in your code manually) it creates the data for you and sets the version number.

Well, I didn´t think about that, sounds like a good solution. Thanks!


text:
how to display text to 8x8 matrix with 64-bit long integers?
I have an array of 64-bit integers to display on an 8x8 led matrix
const int LEN1 = sizeof(Hours);
const uint64_t Hours[] = {
  0x00043c3c3c3c3c00,
  0x000c3c3c3c3c3c00,
  0x001c3c3c3c3c3c00,
  0x0000001818000000,
  0x0000001818100000,
  0x0000001818180000,
  0x00000018181c0000,
  0x000000181c1c0000,
  0x0000001c1c1c0000,
  0x0000041c1c1c0000,
  0x00000c1c1c1c0000
};

and here I have a loop to display it:
void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++) {
    byte row = (image >> i * 8) & 0xFF;
    for (int j = 0; j < 8; j++) {
      lc.setLed(0, i, j, bitRead(row, j));
    }
  }
}

but I can't use a loop in this way and I'm not proficient in byte shifting principles too.
can you please explain how the loop above works or help me to write this loop as
const int LEN1 = sizeof(Hours);

void displayImage(Hours[]) {
  for (int i = 0; i < LEN1; i++) {
    //display Hours
    }
}

it is about displaying text on 8x8 led matrix using arduino/

its not really about loops in c++,  what would be helpful is more detail about the hardware, platform, and the libraries in use. Data-types and libraries seem to be the main issues here.

@jsotola, it is an Arduino question. it is about the use of Arduino's Print.print(num, HEX) function which doesn't have a version for uint64_t type so it must be replaced with at least two prints and the leading 0 must by handled

@Juraj i am probably missing something then ... i see no Serial.print code in OP's listing ... deleted my comments

@jsotola, sorry, some display libraries implement base class Print and the Answer by j0h confused me to think it is the case in this Question

ok, well there are some things I don't know about your code, and hardware, like if the LCD library can handle uint64_t datatypes. I know the Serial.print() function can only handle up to a unit32_t, so I'm using that.
I think your length variable might not be the right length, you might want to add in a check for that in your code. Much of the Arduino code is 8 bit.
void setup() {
Serial.begin(9600);
uint32_t b = 0x0;

const uint64_t Hours[] = {
  0x00043c3c3c3c3c00,
  0x000c3c3c3c3c3c00,
  0x001c3c3c3c3c3c00,
  0x0000001818000000,
  0x0000001818100000,
  0x0000001818180000,
  0x00000018181c0000,
  0x000000181c1c0000,
  0x0000001c1c1c0000,
  0x0000041c1c1c0000,
  0x00000c1c1c1c0000
};

//const int LEN1 = sizeof(Hours[0]);
const int LEN1 = sizeof(Hours)/sizeof(uint64_t);
       Serial.print("Length: ");
       Serial.println(LEN1);

   for (int i = 0; i < LEN1; i++) {
       b=Hours[i]>>16;
       Serial.println(b,HEX);
       }
}

void loop() {
}

I think this code will do what you want, at least as I understand it.
beware of what data-types your LCD library can handle.

welp, I see where I borked this code, but im tired and huingry, and gotta go home. But I still think this will put you close to where you want to be


text:
Listening Serial Ports
guys. I need your help. I have 6 Serial Channels and I need to listen this channel and be sure which channel is working? How can I do that? Can I listen this channel by using digital inputs? Or Do I have to use a devices which has a 6 Serial ports? Like 2 Arduino Mega?

Are they TTL UART or true RS-232?

They are working on RS-232 level. I am going to use RS-232 TTL Converter

And you don't care about what the data is, only if there is data?

Yes, exactly. I just need to check is there data

Possibly a better way to ask the question - is all that is necessary it to see electrical activity on the RS232 Data Receive line?  No matter if it makes sense?  Even if it is noise?   Then the answer might be to use external latching registers and sample the registers using an Arduino. But if we need to make sense of the data, then it may be best to use 6 Arduinos to monitor 6 RS232 serial inputs using the HW UART in each Arduno.  Which is it?

For your needs you don't need actual UARTs. You can do it all with normal GPIO pins and one (or more) interrupts.
UART communication is characterised by having a "start bit" at the beginning of all bytes. That is, in TTL terms, a transition from HIGH to LOW. You just need to look out for that transition.
You could:

Use Pin Change interrupts on 6 pins to monitor for any FALLING transistion, or
Use one interrupt pin with a wired OR of all the signals along with individual pins for each signal to determine which triggered the interrupt.

To determine "is it active" you just need to know that an interrupt has occurred and which pin triggered it, and has that been seen within a certain time period (to be decided by you).


text:
Unable to import the libraries correctly
I am trying to use the Arduino IDE 1.8.15 to program my Arduino. When I download the following code along with the libraries from the same link: https://github.com/SolidGeek/VescUart and using the example: https://github.com/SolidGeek/VescUart/tree/master/examples/getVescValuescompile it, it seems to giving me an error that the VescUart file seems to be missing. I did ctrl+shift+N and also tried adding the library files and these library files are in the same folder as the .ino code. but still it keeps giving me that the header file is missing. Can someone help me with this please?
Error message below:
Arduino: 1.8.15 (Windows Store 1.8.49.0) (Windows 10), Board: "Arduino MKR NB 1500"

getVescValues:9:10: fatal error: VescUart.h: No such file or directory

 #include <VescUart.h>

          ^~~~~~~~~~~~

compilation terminated.

exit status 1

VescUart.h: No such file or directory

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Also attached is the image for reference

Please put the library in your library folder

Thanks! that worked

Does this answer your question? I have downloaded the library but not sure what went wrong


text:
Arduino NANO clone not detected by computer
I recently purchased 5 Arduino Nano clones and on my Windows PC they were all working fine.
I then gave one to a friend and after installing the CH34OC driver on his Mac he was able to program a simple Morse code blink program that worked fine on the device. However, after uploading it the COM port was no longer showing and his Mac could no longer detect the device.
We verified that the problem was not with the Serial cable and not with the USB port and other the Arduino clones worked perfectly also. So it must be an issue with the device which when connected the RX and TX lights would stay on and the inbuilt LED would display the Morse code as was programmed. The device would then no longer even be registered by my computer as no noise was made when plugging it in and nothing showed up in device manager as if I simply pugged in a USB cable with nothing attached.
I then used my Arduino UNO to run the Arduino ISP program and then burn the bootloader onto my NANO. This was successful and the a new blink program was loaded and the TX light no longer shows when connected to my computer but it is still entirely undetected as if nothing was plugged in.
I have tries many things including but not limited to:
Holding the reset button when plugging it in
Reinstalling the driver as administrator
Switching out the cable
Changing the USB port
Using the old bootloader
Reinstalling the Arduino IDE
Restarting my computer.
Sadly nothing is working and I am out of ideas. Does anyone have any suggestions for a fix or know how I can diagnose the issue further. For example checking to see if the USB chip on the Arduino is operational or maybe the diode was faulty? Methods for testing these things would be greatly appreciated.

It sounds rather like a fault with the Nano's CH340 chip, the one used to communicate over USB between the Nano and a PC. The Atmega 328p seems to be working, as you say the previously loaded Morse Code program still runs. I expect you can still program the Atmega entirely through its ISP.
If the CH340 has been physically damaged, you can still program the Atmega processor via the ISP but you will no longer have USB capability on-board. You could use a CH340- or FTDI-cable (USB <-> TTL serial) connected to Arduino-pins 0 and 1 to provide off-board USB communication if you want to continue using the Nano as usual.
Update:

Is there any way that I can verify that the CH340 chip has indeed been
damaged as if it is something smaller like a diode I may attempt to
repair it.

I don't know of a way unless a visual inspection shows a bad component. Not that there might not be one, just that that level of board repair is beyond my expertise. And assuming you didn't ever see or smell smoke, I wouldn't expect the defect to be visible. No harm in going over it with a strong magnifier, though....

So I am assuming my best course of action will simply be to program it through ISP then place it in a permanent project.

Is there any way that I can verify that the CH340 chip has indeed been damaged as if it is something smaller like a diode I may attempt to repair it.


text:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
Heres my code:
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "wifiSSID";
const char* password =  "wifiPassword";

int sleepTime = 0;
HTTPClient http;

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

  Serial.println("START WIFI");
  WiFi.begin(ssid, password);

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

  http.begin("http://ip-address:3000/start?appid=1%2B6vIswDqSmXONCjq4rLtTMd9O2CHEQ4Oe");
  int httpCode = http.GET();
  String payload = http.getString();

  StaticJsonDocument<256> doc;
  deserializeJson(doc, payload);
  sleepTime = doc["sleep"];

  if (sleepTime > 0) {
    Serial.println("Sleeping for: " + sleepTime);
    delay(sleepTime);
    sleepTime = 0;
  }
}

void loop() {
  // Sensor stuff
}

Heres the error:
START WIFI
.........Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC      : 0x4000c271  PS      : 0x00060034  A0      : 0x8008a48c  A1      : 0x3ffb1c60
A2      : 0x3ffb0058  A3      : 0x3f41ae58  A4      : 0x00000014  A5      : 0x3ffbfea0
A6      : 0x3ffbfee8  A7      : 0x00000001  A8      : 0x00000001  A9      : 0x3f41ae59
A10     : 0x000000a5  A11     : 0x30303030  A12     : 0x8008b043  A13     : 0x3ffbfe70
A14     : 0x00000008  A15     : 0x00000001  SAR     : 0x00000012  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffa

ELF file SHA256: 0000000000000000

Backtrace: 0x4000c271:0x3ffb1c60 0x4008a489:0x3ffb1c80 0x4008c034:0x3ffb1ca0 0x4008bfea:0x3ffb1cc0 0x400d5e5c:0x3f725c88

Core 0 register dump:
PC      : 0x40165582  PS      : 0x00060634  A0      : 0x8015196e  A1      : 0x3ffbc120
A2      : 0x00000000  A3      : 0x00000001  A4      : 0x80084032  A5      : 0x3ffbf870
A6      : 0x00060d20  A7      : 0x00000000  A8      : 0x801503f6  A9      : 0x3ffbc0f0
A10     : 0x00000000  A11     : 0x00000001  A12     : 0x80084032  A13     : 0x3ffbf870
A14     : 0x00000000  A15     : 0x3ffbc218  SAR     : 0x00000000  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000

ELF file SHA256: 0000000000000000

Backtrace: 0x40165582:0x3ffbc120 0x4015196b:0x3ffbc140 0x4008b031:0x3ffbc160 0x40089882:0x3ffbc180

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

What should I do?

I got this problem too with the latest IDF version..
check the IDF version as it seems the problem with RTOS handling both cores together.
The solution was for me to downgrade the IDF version to 3.0.0

I suppose your are using Arduino IDE (maybe 1.x.x), if so, you should install the exception decoder so your can read such hex codes. They will give an more useful hint about the error location.
Here the link:
https://github.com/me-no-dev/EspExceptionDecoder

"Decode Failed"

Which Arduino core version are you using? Remember you have to compile and upload aging your sketch, then when the exception happens, copy and paste all those code in exception decoder

ooooh I pasted in the actual exception


text:
MPU6050 Calibrating Accelerometer
I recently got an MPU6050 and I noticed the accelerometer data was a bit off, especially on the Z axis.
I'm running it on a Teensy 4.0 with Adafruit's MPU6050 library and basic example code: https://github.com/adafruit/Adafruit_MPU6050/blob/master/examples/basic_readings/basic_readings.ino
While stable on a flat surface (+Z up), it's reading ~8.5 m/s^2 and when flipped over (-Z up), ~11.6 m/s^2:
+Z:
Acceleration X: -0.06, Y: 0.00, Z: 8.44 m/s^2
-Z:
Acceleration X: -0.01, Y: -0.07, Z: -11.57 m/s^2

Aligning the other axes vertically gives me:
+X:
Acceleration X: 10.16, Y: -0.16, Z: -0.03 m/s^2
-X:
Acceleration X: -9.27, Y: -0.10, Z: -0.18 m/s^2
+Y:
Acceleration X: 0.07, Y: 9.55, Z: -0.10 m/s^2
-Y:
Acceleration X: 0.04, Y: -9.93, Z: -0.05 m/s^2

The X and Y readings could be adjusted fairly close to 9.81 m/s^2 with just an offset, but it seems like the Z axis would also require some scaling.
My question, is there a standard method of calibrating it in code?

Yes an accelerometer can be calibrated.  An offset for each of the 3 accelerometers can be found such that the absolute value of the maximum and minimum values of any given accelerometer axis are equal.  The maximum and minimum values can be found by rotating the accelerometer such that each axes is pointed directly toward and directly away from the earth.  Once each axes is normalized each axes needs a magnitude adjustment value such that the maximum value of all axes equal one another.  It may be convenient the product of the maximum of any given axes and that axes' magnitude adjustment value is 9.8 (meters per second * second).

Would you have an article or link you can share so we can have a look. I understand what you're saying but have no idea how to actually do it.

It's a little difficult to find an appropriate article.  This NIST article goes way overboard assuming the 3 accelerometers may not even be orthogonal.  And other articles skip over accelerometer calibration (to be honest, accelerometers are usually good out of the box for most Arduino applications).  Try this Adafruit article it sounds like what you are after.

Thank you for your comment

Yes. Jeff Rowberg's library performs the calibration for you when you power on. You'll need to make sure the module is lying level and still and then send a character over serial to trigger the calibration. A version based on Jeff's library, called Electronic Cats, can be downloaded directly using the Arduino IDE.
Note that Jeff's library is a bit overwhelming/intimidating for new users. If you'd like to learn more about hiding its complexity behind a simple and easy to use interface, or about being able to save the calibration results to persistent memory so that you don't have to perform the calibration every time you power on, or just want to learn more about this topic in general, please consult the following tutorial:
https://youtu.be/k5i-vE5rZR0


text:
ESP32 WROOM32 SPI EMF issues
I'm trying to run Waveshare SSD1327 128x128 screen via SPI on ESP32 WROOM32 board. On ESP8266 (D1R1?) it works flawlessly while using HW SPI but when I run it on esp32, anything connected to mains which is sitting <50cm from screen will glitch it out completely. Even if I just hold in one hand phone charger cable connected to mains, and come close to screen with my other hand(at least 1m distance between hands), screen will instantly glitch and shut down.
I'm pretty sure this is not connection issue, since it works on ESP8266 and I even tried soldering wires directly to ESP32 board.
I am using VS Code PlatformIO and Arduino framework. I tried setting CPU freq to 40MHz by adding line to platformio.ini and calling setCpuFrequencyMhz(40); in my setup() function. I don't have oscilloscope to confirm that this actually happend. I read somewhere that this .ini thing didn't work.
I am using U8g2lib for screen which is using global SPI object. Even tho I bought screen from Waveshare I can't use WS implementation. MIDAS one is the only implementation which works for me.  Since my board doesn't have all VSPI pins, I had to set them manually in SPI.begin(...):
U8G2_SSD1327_MIDAS_128X128_F_4W_HW_SPI display(U8G2_R0, /* cs=*/ 39, /* dc=*/ 16, /* reset=*/ 2);
...
...
pinMode(39, OUTPUT);
pinMode(14, OUTPUT);
pinMode(13, OUTPUT);
pinMode(12, INPUT);

digitalWrite(39, LOW);
// sck, miso, mosi, ss
SPI.begin(14, 12, 13, 39);
display.begin();

BTW, SW SPI worked extremely slow for me(display.sendBuffer() takes about 1sec), on both ESP32 WROOM32 and ESP8266 D1R1 mini. Friend of mine is using ESP32 WROOVER board and even SW SPI is working for him great without any glitching.

I would suggest you check all of your ground and power connections. Also all unused ESP32 pins should be terminated. You can simply set them as outputs and turn them on to low.

Isn't gpio39 only an input? I am not sure that you can set it as output.

Problem was GPIO39 which is internally connected to a hall sensor... Once I changed CS to some other pin, everything started working...
Having pin cheatsheet would be really helpful in these situations.


text:
Can you use multiple arduinos to run two programs simultaneously?
If I want to run 2 different programs simultaneously, can I do this with 2 arduinos wired together?
Context: I’m building a robot that will balance with reaction wheels while doing other tasks. I would like to have the balancing program running continuously in the background while the servos that control the robot are moving. Can I accomplish this by having a 2nd arduino running the balancing while the 1st arduino controls the rest of the robot?

yes, yes, and yes ..... good luck with your project

You can go with Teensy 4.0 - it's so powerfull, it should be able to handle everything (if it's written correctly). Or maybe Raspberry pi pico with two cores - but I'm not sure if the Arduino core supports it (mbed might be: https://forum.arduino.cc/t/multicore-on-raspberry-pi-pico/858908/15 )

Why do you think a single arduino is not enough to run a sketch with a combined program? You just need non-blocking code.

The answer is yes, you can run two programs one in each Arduino. There are no restrictions on doing this. There are probably millions of Arduinos currently operating without any interaction with each other. In your robot they would need some sort of communications between them. This is if there is to be any type of interaction between them. I do not know your skill set but it may be  possibly do it with one with some tight code.


text:
Set Value for a characteristic fails using BLE ESP32
I'm working on a project that uses a Raspberry pi to trigger a microcontroller to read data from an accelerometer for some amount time then have that data available for the RPi to read it over BLE. I Have been able to set up my ESP32 Thing plus as a server and used both a RPi and the BLE scanner app to send it a message a start it to record data. I am struggling to get this data to be set at the characteristic value so that my RPi can then read it.
My aim is to convert that data from an accelerometer that is stored in an array to a string which can then be read by the RPi.
I have tried to just set the value in my code with some string and the actually value I want to send but both of them fail and cause the controller to reboot.
Is it something to do with the way I am setting up the data or is the code structure fundamentally wrong? please see code below.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

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

#define SERVICE1_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC1_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

#define CHARACTERISTIC2_UUID "279766d1-630f-4db9-9b84-81731a59d46b"

#define CHARACTERISTIC3_UUID "837c3fbd-77e6-43ad-9921-c3526139a7dc"

BLECharacteristic *pCharacteristic1;
BLECharacteristic *pCharacteristic2;
BLECharacteristic *pCharacteristic3;

//Accelerometer Variable
const int xpin = A2;                  // x-axis of the accelerometer
const int ypin = A4;                  // y-axis
const int zpin = A3;                  // z-axis (only on 3-axis models)
int LoopCounter = 0;
const int ArraySize = 250;
int XValueArray[ArraySize];
int YValueArray[ArraySize];
int ZValueArray[ArraySize];
int AValueArray[ArraySize];
char XValueString[500] = "";
char YValueString[500] = "";
char ZValueString[500] = "";
bool MeasurmentTaking = false;
bool ValidMessage = false;
int XValue = 0;
int YValue = 0;
int ZValue = 0;
//Millis variables
unsigned long PreviousMillis = 0;
unsigned long CurrentMillis = 0;
const int PeriodRead = 4;
const int NumberOfPoints = 250;

//Class to read incomming messages
class MyCallbacks: public BLECharacteristicCallbacks {

    void onWrite(BLECharacteristic *pCharacteristic1) {
      std::string RecievedValue = pCharacteristic1->getValue();

      if (RecievedValue == "Start") {
        MeasurmentTaking = true;
        ValidMessage = true;
      }//If
      else{
        }//Else
    }
};

void setup() {
  Serial.begin(115200);
  //Set up accelerometer pins
  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT);

  //Set up BLe device
  BLEDevice::init("MyESP32");

  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE1_UUID);               //XAxis accellerometer
  BLECharacteristic *pCharacteristic1 = pService->createCharacteristic(
                                         CHARACTERISTIC1_UUID,
                                         BLECharacteristic::PROPERTY_READ   |
                                         BLECharacteristic::PROPERTY_WRITE  |
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );

  BLECharacteristic *pCharacteristic2 = pService->createCharacteristic(       //YAxis accellerometer
                                         CHARACTERISTIC2_UUID,
                                         BLECharacteristic::PROPERTY_READ   |
                                         BLECharacteristic::PROPERTY_WRITE  |
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );

  BLECharacteristic *pCharacteristic3 = pService->createCharacteristic(       //ZAxis accellerometer
                                         CHARACTERISTIC3_UUID,
                                         BLECharacteristic::PROPERTY_READ   |
                                         BLECharacteristic::PROPERTY_WRITE  |
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );

  pCharacteristic1->setCallbacks(new MyCallbacks());

  pCharacteristic1->setValue("X");
  pCharacteristic2->setValue("Y");
  pCharacteristic3->setValue("Z");
  pService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE1_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
}

void loop() {
  Serial.print(MeasurmentTaking);
  Serial.println(ValidMessage);

  //Record Data from accelerometer to array
  if (ValidMessage == true){
    MeasurmentTaking = true;
    while (MeasurmentTaking == true){
          CurrentMillis = millis();
          if (LoopCounter == NumberOfPoints){
            MeasurmentTaking = false;
            LoopCounter = 0;
            }//If
          else if(CurrentMillis - PreviousMillis >= PeriodRead){
            int XValue = analogRead(xpin);
            Serial.println(XValue);
            XValueArray[LoopCounter] = XValue;

            int YValue = analogRead(ypin);
            Serial.println(YValue);
            YValueArray[LoopCounter] = YValue;

            int ZValue = analogRead(zpin);
            Serial.println(ZValue);
            ZValueArray[LoopCounter] = ZValue;

            AValueArray[LoopCounter] = ZValue;
            PreviousMillis = CurrentMillis;
            LoopCounter = LoopCounter + 1;
            }//Else If

          }//While

    //Convert array values to string
    Serial.print("XValueArray");
    for (int i = 0; i <= ArraySize; i++){
      Serial.println(XValueArray[i]);
      int buff1 = XValueArray[i];
      char str1 [7];
      sprintf(str1,"%u" ,buff1);
      strcat(XValueString,str1);
      strcat(XValueString, ",");
      }//For
    Serial.println();
    Serial.print("YValueArray");
    for (int j = 0; j <= ArraySize; j++){
      Serial.println(YValueArray[j]);
      int buff2 = YValueArray[j];
      char str2 [7];
      sprintf(str2,"%u" ,buff2);
      strcat(YValueString,str2);
      strcat(YValueString, ",");
      }//For
    Serial.println();
    Serial.print("ZValueArray");
    for (int k = 0; k <= ArraySize; k++){
      Serial.println(ZValueArray[k]);
      int buff3 = ZValueArray[k];
      char str3 [7];
      sprintf(str3,"%u" ,buff3);
      strcat(ZValueString,str3);
      strcat(ZValueString, ",");
        }//For
    Serial.println();
    Serial.print("XvalueString");
    Serial.println(XValueString);
    Serial.print("YvalueString");
    Serial.println(YValueString);
    Serial.print("ZvalueString");
    Serial.println(ZValueString);
    MeasurmentTaking = false;

    //Set values as new data
    pCharacteristic1->setValue("Test X");
    pCharacteristic2->setValue("Test Y");
    pCharacteristic3->setValue("Test Z");
    ValidMessage = false;
  }
  else{
    }

  delay(1000);
}

Example of the string I would like to send.
<1967,1967,1989,2000,2000,2000,2003,1997,1984,1980,1999,1999,2000,2000,2021,2000,1969,1973,1999,2000,1999,1995,1995,1986,1978,1998,1991,2000,2002,1999,2000,1968,1989,1995,2000,2000,2000,2001,1983,1979,1993,2000,1997,2002,2000,1999,1967,1986,1988,1999,2000,2001,2000,1983,1971,2059,1999,2000,2000,1997,2000,1963,1989,1997,2000,1999,2015,2003,1984,1979,1986,2003,2000,1997,2001,2001,1968,1984,1991,1998,1997,1998,2000,1981,1979,2000,2000,2002,2002,1999,2000,1968,2016,1997,2000,2000,2000,2001,1981,1982,1991,2000,2000,2001,2000,2000,1967,1987,1998,2005,2001,2000,2001,1984,1980,2000,2000,2000,2000,2001,1998,1967,1994,2000,2000,2000,2000,1997,1985,1981,1996,2000,2000,2000,2000,2000,1971,1989,1999,2001,2001,2000,2000,1984,1970,1999,2001,2000,2000,1999,2000,1968,1987,2000,1990,2000,2001,1997,1985,1980,1995,2000,2000,1999,2000,2000,1968,1989,1997,2000,2000,2002,2006,1984,1979,1994,1998,1998,2000,2000,2000,1968,1990,1997,2000,1999,1998,2000,1983,1980,1998,2000,1997,1999,1998,2002,1963,1985,2000,2000,1999,2002,1999,1983,1971,1995,1989,1985,2000,1999,2000,1966,1989,2001,2000,2000,1983,2000,1982,1978,1997,2000,2000,2001,2003,1999,1967,1989,1997,1999,2000,2002,1999,1997,1979,1997,1999,1999,1999,1999,2000,1968,1990,1999,1999,2002,2000,2000,1983,1978,1859>

Thank you for any help or guidance to an answer.


text:
Unable to get readings for "Motor with Encoder"
I've posted to the DFRobot forum, who makes the FIT0186 motors, but no one seems to be replying there.  So, excuse the copy pasting.  It's probably an issue with the motor/encoder, but perhaps it has to do with the arduino.  I'm using a Nano, and a TB6612 based motor driver from DFRobot.
I'm trying to get the built-in encoder working for the FIT0186.
The example wiki code doesn't work, and I've modified it as far as I can using sensible changes.
I'm plugging both Hall Sensor A and B outputs to the interrupts.
Currently, when I plug in the 12V, it triggers an interrupt, but then other than that initial pulse, no interrupts are triggerred.
The motor is moving as expected. Attaching my code. Has anyone got the encoder working?
const byte encoder0pinA = 2;
const byte encoder0pinB = 3;
volatile int posA;
volatile int posB;

int DIR1 = 8;
int PWM1 = 9;

void setup()
{
  Serial.begin(115200);
  pinMode(DIR1, OUTPUT);
  pinMode(PWM1, OUTPUT);
  pinMode(encoder0pinA,INPUT);
  pinMode(encoder0pinB,INPUT);
  attachInterrupt(digitalPinToInterrupt(encoder0pinA), encoderA, RISING);
  attachInterrupt(digitalPinToInterrupt(encoder0pinB), encoderB, RISING);

}

void loop()
{
  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  noInterrupts();
  posA = 0;
  posB = 0;
  interrupts();

  delay(100);

  int value;
  digitalWrite(DIR1, HIGH);

  for(value = 0 ; value <= 255; value += 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  delay(100);

  for(value = 255 ; value >= 0; value -= 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);
  delay(100);

  digitalWrite(DIR1, LOW);
  for(value = 0 ; value <= 255; value += 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  delay(100);
  for(value = 255 ; value >= 0; value -= 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

}

void encoderA()
{
    posA++;
}

void encoderB()
{
    posB++;
}

that is probably a quadrature encoder ... it has two channels, A and B ... monitor state of A ... at one of the signal edges, check the state of B ... that will tell you the direction of rotation ... for example, check the state of B every time A goes from high to low

Hmm so that was interesting.  When checking now, B increases.  But then when I touch D4, it goes to 0.  Oh boy, magic hour.

From what you have indicated (being wired correctly) there is a high probability you have a bad connection. It could be one of many things such as a loose wire, broken wire, problem with the module, etc... Swp A & B and see what happens.

Thanks, I had the hall sensor gnd and vcc backwards.