message:
Keeping track of multiple actions

I have a number of LED's connected to an Arduino which receives a JSON dict.

The JSON dict determines which action the LED's follow (either a fade, a pulse, on, or off), but I'm having trouble working out how to get one LED to flash whilst another fades etc.

The important parts of the code looks like this:

    int led_choice;
    int led_brightness;
    String pattern_name;
    int pattern_length;

    // Timer Setup
    unsigned long led1_current_time;
    unsigned long led2_current_time;
    unsigned long previousFadeMillis[2];
    unsigned long previousPulseMillis[2];
    unsigned long current_time;

    // fade setup
    int fadeInterval = 50;
    int fadeIncrement = 5;
    int fadeDirection = 1;
    int fadeValue = 0;
    int maxPWM = 255;
    int minPWM = 0;
    int translated_pin;

    // Pulse setup
    int pulse_state = 0;

    void setup() {
      pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
      Serial.begin(115200);
    }

    void loop() {

      current_time = millis();

      // CODE HERE TO READ SERIAL/MQTT, DECIPHER JSON AND EXTRACT VARIABLES

      if ( pattern_name == "fade"){
        fade(current_time, pattern_length, led_brightness, led_choice);
      } else if ( pattern_name == "pulse"){
        pulse(current_time, pattern_length, led_brightness, led_choice);
      }
      else if (pattern_name == "on" )
      {
        solid_running(led_choice, led_brightness);
      }
      else {
        switch_off(led_choice);
      }
    }

    /********** LED CONTROL FUNCTIONS *********/
    void fade(unsigned long thisMillis, int fadeInterval, int maxPWM, int led_pin) {
      if (thisMillis - previousFadeMillis[led_pin] >= fadeInterval) {
        // yup, it's time!
        if (fadeDirection == 1) {
          fadeValue = fadeValue + fadeIncrement;
          if (fadeValue >= maxPWM) {
            // At max, limit and change direction
            fadeValue = maxPWM;
            fadeDirection = 0;
          }
        } else {
          //if we aren't going up, we're going down
          fadeValue = fadeValue - fadeIncrement;
          if (fadeValue <= minPWM) {
            // At min, limit and change direction
            fadeValue = minPWM;
            fadeDirection = 1;
          }
        }
        // Only need to update when it changes
        analogWrite(led_pin, fadeValue);
        // reset millis for the next iteration (fade timer only)
        previousFadeMillis[led_pin] = thisMillis;
      }
    }

    void pulse(unsigned long thisMillis, int on_duration, int on_speed, int led_pin){
      if (thisMillis - previousPulseMillis[led_pin] >= on_duration) {
        // save the last time you blinked the LED
        previousPulseMillis[led_pin] = thisMillis;

        // if the led is off turn it on and vice-versa:
        if (pulse_state == 0) {
          pulse_state = 1;
          // set the led with the ledState of the variable:
          analogWrite(led_pin, 255);
        } else {
          analogWrite(led_pin, 0);
          }
          pulse_state = 0;
        }
      }
    }

    void switch_off(int led_pin){
        analogWrite(led_pin, 0);
    }

    void solid_running(int led_pin, int led_brightness){
        analogWrite(led_pin, led_brightness);
    }

If I send the json data telling LED 1 to pulse, as soon as I send a second string telling LED2 to fade, LED 1 stops pulsing.

I'm sure this is something obvious, but it's been driving me mad for days!

*EDIT: Adding the second attempt at this*

    // Declare the number of LED's
    const int led_count = 2;

    // Setup the ENUM for the various Modes
    enum EMode { Off, On, Pulse, Fade };
    // Create the struct and initialise it
    struct MMode {
      EMode pin_mode;
      int action_pin;
      int action_delay;
      int action_max;
      int action_min;
      int fade_direction;
      int fade_value;
      int fade_increment;
      unsigned long m_current_time;
      unsigned long previous_millis;
    } leds[led_count] {
      {Fade, D4, 20, 255, 0, 1, 0, 1, 0, 0},
      {Fade, BUILTIN_LED, 20, 255, 0, 1, 0, 1, 0, 0}
    };

    void setup() {
      Serial.begin(9600);
      // Setup the Built-in LED
      pinMode(BUILTIN_LED, OUTPUT);
      // Setup the Red LED
      pinMode(D4, OUTPUT);
    }

    void loop() {
        for (int n = 0; n < led_count; n++) {
          leds[n].m_current_time = millis();
          switch(leds[n].pin_mode){
            case Fade:
              fade(leds[n]);
              break;
          }
        }
    }

    /********** LED CONTROL FUNCTIONS *********/
    void fade(struct MMode led) {
      if (led.m_current_time - led.previous_millis >= led.action_delay) {
        // yup, it's time!
        if (led.fade_direction == 1) {
          led.fade_value = led.fade_value + led.fade_increment;
          Serial.print("Fade Up Value: ");
          Serial.print(led.fade_value);
          Serial.println("    ");
          if (led.fade_value >= led.action_max) {
            // At max, limit and change direction
            led.fade_value = led.action_max;
            led.fade_direction = 0;
          }
        } else {
          //if we aren't going up, we're going down
          led.fade_value = led.fade_value - led.fade_increment;
        //  Serial.print("Fade Down Value");
        //  Serial.print(led.fade_value);
        //  Serial.print("    ");
          if (led.fade_value <= led.action_min) {
            // At min, limit and change direction
            led.fade_value = led.action_min;
            led.fade_direction = 1;
          }
        }
        //Serial.print(led.fade_value);
        //Serial.print("  ");
        // Only need to update when it changes
        analogWrite(led.action_pin, led.fade_value);
        // reset millis for the next iteration (fade timer only)
        led.previous_millis = led.m_current_time;
        //Serial.print(led.previous_millis);
        //Serial.print("  ");
      }
    }

This second iteration of the code appears to define the led's using the struct correctly, however when I upload it to the arduino, motor.fade_value gets set to 1, and never increments above this.

I get the feeling I'm missing something from the answers that I've had so far, but I'm not sure what that something is, and google isn't proving very helpful tonight...

body:
Without looking to the entire code, the best way is to use a 'mode' for each led. So for each led, keep track how it should behave (like Off, On, Blink, FadeOff, FadeOn etc) and some parameters (for the speed for fading for example). You can use a struct for this, like

    enum EMode { Off, On, Pulse, FadeOff, FadeOn };
    struct LedMode
    {
       EMode mode;
       int fadeSpeed; // Only used when mode = fade off/on
    };

    LedMode ledModes[8]; // For e.g. 8 leds

When you get a JSon command, change the ledMode structure for that LED accordingly.

Than in the main loop use something like:

    loop()
    {
        for (int n = 0; n < 8; n++) // For each led
        {
           switch (ledModes[n].mode)
           {
           case Off:
             TurnOff(ledModes[n]);
             break;

           case On:
              TurnOn(ledModes[n]);
              break;

           case Pulse:
              Pulse(ledModes[n]);
              break;

           case FadeOn:
              FadeOn(ledModes[n]);
              break;

           ...
        }
    }

To prevent going into each case all the time, add in the structure a 'Dirty' flag which is set to true by JSON and set to false after performed the change (e.g. you only have to switch a LED On or Off one time, not in every loop). For FadeOn/Off until it has reached 255 or 0. You also can use a PreviousMode and check if the mode has been changed since last time.

And for the Pulse/FadeOn/Off you need to add in the structure the last set value to be able to increase/decrease it, and the time it has changed last time.

Btw, you also can pass n and get LedModes[n] directly since it is global.


sender: user

sender: assistant

body:
you need to call the fade/pulse function every time until the led state's change,

Start by creating full separate state for each LED,

    struct LED_state{
        STATE state;

        unsigned long led1_current_time;
        unsigned long previousMillis;
        int pin;
        int fadeValue;
        int fadeDirection;
        int pulse_state = 0;
    }

    LED_state led[2];

`STATE` is an enum for each animation you do. Change the functions to take a pointer to this state. Initialize them in `init()`.

Then create an update function which looks like:

    void updateLED(LED_state* state){
        switch(state->state){
        case FADE:  fade(state);break;
        case PULSE: pulse(state);break;
        case ON:    solid_running(state);break;
        case OFF:   switch_off(state);break;
        }
    }

Every time through the loop you call this update function for each LED's state.

To change what the LED does you the only need to update the state member in the struct for the LED.

      if ( pattern_name == "fade"){
        led[chosen_led]->state = FADE;
      } else if ( pattern_name == "pulse"){
        led[chosen_led]->state = PULSE;
      } else if (pattern_name == "on" ){
        led[chosen_led]->state = ON;
      } else {
        led[chosen_led]->state = OFF;
      }


message:
'dynamic_cast' not permitted with -fno-rtti

class A {
        virtual ~A();
    }

    class B : public A {
        public:
          int foo;
    }

    void bar(A *foo_){
        B* b = dynamic_cast<B*>(foo_);

        if(b != nullptr){
             cout << (*foo_)->foo << endl;
        }
    }

    int main(){
        B b{};
        bar(b);
    }

Compiling error:

    error: 'dynamic_cast' not permitted with -fno-rtti

I thank sincerely for the help.

body:
It seems avr-gcc version 4.9.2 that is used by the Arduino IDE has been compiled without RTTI support. It defaults to `-fno-rtti`, and if you try turning it on with `-frtti` you just get other horrible linker error messages instead.

So it looks like you can't use `dynamic_cast` on AVR boards.

Googling around it looks like numerous people have tried to enable FTTI on Arduino, but they have either failed and given up, or they have succeeded and never bothered to tell anyone else how they did it (numerous forum posts of "how do you do this?", a bit of discussion, and then they tail off...)

The solution? Either don't use RTTI, or use a more capable microcontroller whose compiler has RTTI enabled.

One way to not use RTTI is to fake it yourself:

    #define CLASS_A 1
    #define CLASS_B 2

    class A {
        public:
            virtual int classType() { return CLASS_A; }
    };

    class B : public A {
        public:
            virtual int classType() { return CLASS_B; }
            void bar() {
                Serial.println("Baaaah!");
            }
    };

    void foo(A *foo) {
        if (foo->classType() == CLASS_B) {
            B *foob = (B *)foo;
            foob->bar();
        } else {
            Serial.println("Sorry, I can't bar.");
        }
    }

    void setup() {
        Serial.begin(115200);
        A a;
        B b;
        foo(&a);
        foo(&b);
    }

    void loop() {
    }

Output:

    Sorry, I can't bar.
    Baaaah!


message:
How to interface USB to custom Arduino Uno Schematic and programming atmega?

I'm fairly new to designing schematics and working with the atmega on its own and I'm designing an arduino schematic on eagle. Ive gotten to the stage where I need to incorporate a TTL USB interface in order to program the chip. I've just became aware that the arduino uses another avr chip to do so but it appears similar to the microcontroller and just need some clarification.

Since I want it all on one board like the arduino uno, my question is how is the USB-B connected to the microcontroller and how would I Incorporate it into my schematic?

Another question (out of curiosity) if I was to mass produce said PCB with one program on the atmega chip and leave out a USB module so people wouldnt be able to reprogram it (without taking the board apart obviously) How would that be done?

Heres a photo of my current schematic:[![enter image description here][1]][1]

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

body:
> Since I want it all on one board like the arduino uno my question is how is the USB-B connected to the microcontroller and how would i Incorporate in my schematic?

The USB interface forms a bridge between the USB connector and the UART of the "master" MCU.  You don't have to use a microcontroller, but almost any UART to USB bridge chip will do the job.  Common ones are the CH340G (cheap and unstable), CP2102, FT232, etc.  The DTR signal from the USB chip is used to reset the main MCU.

You should look at the existing Uno schematics to see how the two chips are wired together.

> Another question (out of curiosity) if I was to mass produce said PCB with one program on the atmega chip and leave out a USB module so people wouldnt be able to reprogram it (without taking the board apart obviously) How would that be done?

You would program the board through the ICSP pins - in the same way that you put the bootloader on.  Normally you'd invest in a proper programmer to connect up to the chip, but you can do it with an Arduino acting as the programmer.


message:
Can you use a RF remote with nRF24L01 and Arduino?

I recently bought a 10 pack of RF transceivers (nRF24L01). I wanted to know if its possible to pair one with an RC drone controller. I can't seem to find any ways to do this through google.

If this helps:

My drone and its controller is called "Sky Viper v2400" and a link to where you buy it is: https://www.amazon.com/Sky-Viper-01601-Streaming-Video/dp/B01D1HRXSK.

Thanks

body: The nRF24 operates in the 2.4GHz frequency and implements a proprietary protocol so, even if I don't have much information on your particular drone/controller, I strongly doubt there's a chance you can use the nRF24 module to talk to your drone.


message:
Problems with NodeMCU and Relay

I've connected the MCU to a cheap chinese 24/12v to 5v car phone charger and hooked some wires to a relay.When I try to program doesn't matter if the pin is set to high or low , as soon as I touch the "IN" wire from the relay into any of the selected pins, the relay auto actives.

here is the schematic
The charger input is hooked to a 12V drill battery for tests and the output to arduino is an usb port that I soldered wires to it's respective poles.

    USB from Chinese charger Positive pole ------- NodeMcu Vin
    USB from Chinese charger Negative pole ------- NodeMcu GND
    USB from Chinese charger Positive pole ------- Relay   VCC
    Relay Ground --------------------------------- NodeMcu Gnd
    Relay DataPin -------------------------------- NodeMcu D0 or D1
And here's the code:

    int port = D0;
    int portB = D1;

    void setup() {
    Serial.begin(115200);
    pinMode(port,OUTPUT);
    pinMode(portB,OUTPUT);

    digitalWrite(port,HIGH);
    digitalWrite(portB,LOW);

    }

    void loop() {

    }

 But the result is that the relay will always be on activated ( IN pin = Low ) even connected to D0 that is high... Any ideas ?

body:
Does your nodemcu directly feed the relay?
If so, 3.3v (nodemcu output high level) is not enough to activate it.
I would use a transistor like a s8050 to Power it (do not forget the freewheel diode on the relay coil)


message:
Interrupts Problem with Flow sensor

#include <Wire.h> //I2C lib
    #include <LCD.h>
    #include <LiquidCrystal_I2C.h>
     // LCD lib
    LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    const int pot_pin = A0;
    const int pump_pwm= 3;

    int press_pin =A1;

    //flowmeter parameters
    int flowPin = 2;  // input pin on arduino D2

    double flowRate;   // value intented to calculate
    double flowR; // flow value in lt
    double totalFlow; // total output of flow from system

    byte sensorInterrupt = 0; // interrupt 0 on D2 pin Arduino Nano

    volatile int count; ////integer needs to be set as volatile to ensure it updates correctly during the interrupt process.

    int pot_init= 0;
    int pump_init= 0;
    int percentValue =0;

    void setup() {

      lcd.begin(20,4);  // A4 - A5 connection SDA - SCL
      lcd.backlight();
      Serial.begin(9600);

      pinMode( flowPin,INPUT); // Set D2 pin as an input

      attachInterrupt(sensorInterrupt,Flow,RISING); // Configures interrupt 0 ( pin D2 on Arduino Nano ) to run function "Flow"
    }

    void flow_control(void) {

      count = 0; // reset counter so it could start counting from 0

      interrupts(); // enables interrupts on arduino nano
      delay(1000); // wait 1000 msec
      noInterrupts(); // disable interrupts on arduino nano

      //calculation for flowmeter

      flowR = (count*8.93);   // 112 pulse/lt 423.84 pulse /gallon
      flowRate= flowR*60;     // convert seconds to minutes, new unit is ml/minutes
      flowRate= flowRate/1000; // convert ml to liters, new unit is lt/minutes

      totalFlow += flowR;

      // Print the flow rate for this second in litres / minute
        Serial.print("Flow rate: ");
        Serial.print(int(flowRate));  // Print the integer part of the variable
        Serial.print("L/min");
        Serial.print("\t");       // Print tab space

        // Print the cumulative total of litres flowed since starting
        Serial.print("Output Liquid Quantity: ");
        Serial.print(totalFlow/1000);
        Serial.println("L");

        lcd.setCursor(0,2);
      lcd.print("Flow: ");
        lcd.setCursor(8,2);
      lcd.print(flowRate);
      lcd.print("lt/min");

      lcd.setCursor(0,3);
      lcd.print("Total: ");
      lcd.setCursor(8,2);
      lcd.print(totalFlow/1000);
      lcd.print("lt");

    }

    void Flow(void)
    {
      count++; // every time this function is called, increment  "count" by 1
    }

    void loop() {

      pressure_cal();
      pump_control();
      flow_control();
      lcd_control();
    }

    void pressure_cal(void) {

      float sensorVoltage = analogRead(press_pin);   // sensor voltage A0
      float psi = ((sensorVoltage-102)/204)*25;  // Offset    0 PSI= 0.5V=102 unit, 50 PSI= 2.5, 100 PSI= 4.5V, 1 PSI= 0.04V

      // calibration
      float bar = psi*(0.0689475729);           // Conversion PSI to BAR

      lcd.setCursor (0,1);
      lcd.print (psi);
      lcd.print (" PSI");

      lcd.setCursor ( 10,1);
      lcd.print(bar);
      lcd.print( " BAR");

      //lcd.setCursor(17,1);
      //lcd.print(sensorVoltage);

      Serial.println (sensorVoltage);
      Serial.println(bar);
      Serial.println (psi);

      delay (100);
    }

    void pump_control(void)

    {

      // read the analog in value:
      pot_init = analogRead(pot_pin);
      // map it to the range of the analog out:
      pump_init = map(pot_init, 0, 1023, 50, 230);  //  duty cycle between   - �: speed control , duty cycle between %0 -  : turned off  , duty cycle between � - 0: full speed
      // map pump speed percent of full scale
      percentValue = map (pump_init, 50, 230,0,100);
      // change the analog out value:
      analogWrite(pump_pwm, pump_init);

      // print the results to the Serial Monitor:
      Serial.print("\t Speed Input = ");
      Serial.print(pot_init);
      Serial.print("\t Speed Output = ");
      Serial.print(pump_init);
      Serial.print("\t Pump Speed Percentage = ");
      Serial.println(percentValue);

      lcd.setCursor(2,0);
      lcd.print("Speed: ");
      lcd.setCursor(8,0);
      lcd.print("%");
      lcd.setCursor(9,0);
      lcd.print(percentValue);
      lcd.print("     ");

     //  delay after the last reading:
      delay(2);

    }

I try to write code including flow sensor, pressure sensor and pump. I wrote the code. But When I use interrupt , code stop. I used functions in " void loop()" . I moved the interrupt code ( flow_control) between void setup and void loop. But I can see outputs in serial monitor but I cannot see on lcd. Could you help me fix the problem ?

body:
A lot of peripheral libraries requires interrupts to be enabled, especially when they use timing or the I2C/SPI pins. Instead of disabling interrupts for the majority of the sketch, what you want to do is isolate disabling the interrupts to *just reading and resetting* the count variable:

    noInterrupts(); // disable interrupts on arduino nano
    local_count = count;
    count=0;
    interrupts(); // enables interrupts on arduino nano

Also all that processing takes some time which will skew the timing so it's better to use timestamp and millis:

unsigned long previous_read;

    if(millis() -  previous_read > 1000){
        noInterrupts(); // disable interrupts on arduino nano
        int local_count = count;
        count=0;
        interrupts(); // enables interrupts on arduino nano
        previous_read += 1000;

        //process flowrate based on local_count

    }


message:
Rc car which returns to middle when left or right button is not pressed

Hi i am currently working on a school project , my only problem is that i want my RC car to return to middle direction (which i have set to 66 in the servo motor) when the left or right button is not pressed . i used if statements but it doesn't work. Are there any function that i can use ?
Here is my code for the transmitter i used the RC-Switch Library (https://www.arduinolibraries.info/libraries/rc-switch)

    #include <RCSwitch.h>
    #include <Servo.h>

    const int IN1 = 3;
    const int IN2 = 4;
    const int trigPin = 5;
    const int echoPin = 6;
    const int Buzzer = 8;
    int distance = 0;
    int value = 0;
    long duration;
    RCSwitch mySwitch = RCSwitch();
    Servo myservo;

    void setup () {
      mySwitch.enableReceive(0);
      myservo.attach(7);
      pinMode(IN1, OUTPUT);
      pinMode(IN2, OUTPUT);
      pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
      pinMode(echoPin, INPUT); // Sets the echoPin as an Input
      pinMode(Buzzer,OUTPUT);
      Serial.begin (9600);    // Debugging only
      Serial.println ("Receiver Ready");
    }

    void loop () {

      delayMicroseconds(10);
      // Clears the trigPin
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      // Sets the trigPin on HIGH state for 10 micro seconds
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      // Reads the echoPin, returns the sound wave travel time in microseconds
      duration = pulseIn(echoPin, HIGH);
      // Calculating the distance
      distance= duration*0.034/2;
      // Prints the distance on the Serial Monitor
      //Serial.print("Distance: ");
      //Serial.println(distance); //distance is the returned integer,

     if (mySwitch.available()) {

        value = mySwitch.getReceivedValue();
        Serial.println (value);

          if(value == 1) {
            forward ();
            Serial.println (" = forward");
          }

          if(value == 2){
            backward ();
            Serial.println (" = backward");
          }

          if(value == 3) {
            left ();
            Serial.println (" = left");
          }

          if(value == 4) {
            right ();
            Serial.println (" = right");
          }
          Serial.print(" ");
        }
      mySwitch.resetAvailable();
      //myservo.write(45);
    }

    void forward () {
      digitalWrite (IN1, LOW);
      digitalWrite (IN2, HIGH);
    }

    //value = mySwitch.getReceivedValue();
    void backward () {

      if ((distance < 50)&& (value == '2'))
      {
        digitalWrite (IN1, LOW);
        digitalWrite (IN2, LOW);
        digitalWrite (Buzzer, HIGH);
      }
      else if ((distance > 50)&& (value == '2'))
      {
        digitalWrite (IN1, HIGH);
        digitalWrite (IN2, LOW);
        digitalWrite (Buzzer, LOW);
      }
    }
    // 66 is middle

    void right () {
      if (value == 4){
        myservo.write(110);
      } else
      myservo.write(66);
    }

    void left () {
      if (value == 3){
        myservo.write(50);
      }else
     myservo.write(66);
    }

And Here is The transmitter code

    // TRANSMITTER CODE

    #include <RCSwitch.h>
    RCSwitch mySwitch = RCSwitch();
    // Assigning controller buttons to Digital Pins
     int forward = 11;
     int reverse = 10;
     int rightTurn = 9;
     int leftTurn = 8;

    void setup () {
      pinMode (forward, INPUT_PULLUP);
      pinMode (reverse, INPUT_PULLUP);
      pinMode (rightTurn, INPUT_PULLUP);
      pinMode (leftTurn, INPUT_PULLUP);
      mySwitch.enableTransmit(7);
      Serial.begin (9600);         // Debugging only
      Serial.println ("Transmitting");
    }

    void loop () {
      if (digitalRead(forward) == LOW) {
        mySwitch.send(1, 24);
        Serial.println ("Forward");
      }

      if (digitalRead(reverse) == LOW) {
        mySwitch.send(2, 24);
        Serial.println ("Reverse");
      }

      if (digitalRead(leftTurn) == LOW) {
        mySwitch.send(3, 24);
        Serial.println ("Left Turn");
      }

      if (digitalRead(rightTurn) == LOW) {
        mySwitch.send(4, 24);
        Serial.println ("Right Turn");
      }
    }

body:
You send values from your transmitter when you press a button but not when you release them. The simplest solution would be sending the state of all buttons in every iteration if the transmitter has enough capacity. (I think it has for just these four values)

Add an enum to make the code more readable:

    enum {
        FORWARD_ON = 0,
        FORWARD_OFF, // It will be 1.
        BACKWARD_ON, // It will be 2 and so on...
        BACKWARD_OFF,
        RIGHT_ON,
        RIGHT_OFF,
        LEFT_ON,
        LEFT_OFF
    };

So a sending function will be like this:

    if (digitalRead(forward) == LOW)
        mySwitch.send(FORWARD_ON, 24);
    else
        mySwitch.send(FORWARD_OFF, 24);
    // And so on for every button...

Then by reception you should add some state variables and store the received values:

    int steer_right = 0;
    int steer_left = 0;

    // ...

    loop() {

    // ...

    value = mySwitch.getReceivedValue();

    switch (value) {
        case RIGHT_ON:
            steer_right = 1;
            break;
        case RIGHT_OFF:
            steer_right = 0;
            break;
        case LEFT_ON:
            steer_left = 1;
            break;
        case LEFT_OFF:
            steer_left = 0;
            break;

        // ... (throttle)

        default:
            break;
    }

    // ...

    }

Then you evaluate what you got:

    if (steer_right && !steer_left)
        right();
    else if (!steer_right && steer_left)
        left();
    else
        straight();

    // ... (throttle)


message:
ESP8266 timer to trigger actions (logic issue)

so I have an application in which there are 2 specific times (eg 9AM, 6PM) where a variable curPos is updated. Everything is converted in ms since 00:00 (9AM = 32400000, 6PM = 64800000). Now, the actions (curPos updates) should be triggered every day at these times. To retrieve the current real time (always in ms) I'm sending a http request to a website. This is done only once in the setup().

The idea is that I have to access somehow (http request) the current real time in order to determine when are 9AM and 6PM in my ESP8266, since the start of the sketch. The current real time is needed only once at the beginning (in case there's an issue and the sketch restarts).
Then I can calculate the difference between the current real time and the timers.

The next step would be to translate the values into a 24hour cycle starting at the startup/reset time, so that it can repeat itself without need to request again the real time.

I'm lost in the logic on how to deal with this and with millis() to check when it's time to trigger one of the actions.

This is what I'm doing now with the HTPP GET payload in the setup() (I can successfully retrieve the 3 values in ms from the GET response)

          String payload = http.getString();

          int commaIndex = payload.indexOf(',');
          int secondCommaIndex = payload.indexOf(',', commaIndex + 1); //Search for the next comma just after the first

          mainTime = payload.substring(0, commaIndex).toInt(); //current real time in ms
          timers[0] = payload.substring(commaIndex + 1, secondCommaIndex).toInt(); //9AM in ms
          timers[1] = payload.substring(secondCommaIndex + 1).toInt()); //6PM in ms

          timers[0] = abs(mainTime - timers[0]); //the time difference before reaching the first timer (in ms)
          timers[1] = abs(mainTime - timers[1]); //the time difference before reaching the second timer (in ms)

          // my attempt to turn the time differences into a 24hrs "local" (in the sketch) time
          //dayMs is 24hrs in ms (86400000)
          if(timers[0] < 0)
            timers[0] = dayMs - timers[0];

          if(timers[1] < 0)
            timers[1] = dayMs - timers[1];

and in the loop I'd need a comparison (I think) but I'm just really lost on this

    //I think millis need to be reset after 24hrs since the start of the sketch?

    if(millis() == timers[0]){
          curPos = 1; //first timer expired then trigger
      }else if(millis() == timers[1]){
          curPos = 7; //second timer expired then trigger
      }

thanks!

body:
I describe how I do it in my project. I use the Time library a.k.a TimeLib. I set the time I retrieved not by NTP but over modbus from a device which is the source of other data in my project. In your case, you have the http request.

The input to set the time to TimeLib is UNIX epoch. Epoch are seconds from 1970-01-01. If you set only the seconds of the current day, the date would stay 1970-01-01.

And then I have for example this function

    boolean restHours() {

      const int BEGIN_HOUR = 9;
      const int END_HOUR = 22;

      int hourNow = hour(now());

      if (hourNow >= BEGIN_HOUR && hourNow < END_HOUR) {
        if (state == RegulatorState::REST) {
          state = RegulatorState::MONITORING;
        }
        return false;
      }
      if (state == RegulatorState::MONITORING) {
        state = RegulatorState::REST;
        clearData();
      }
      return true;
    }

`now()` returns the 'epoch' time. ` hour(now())` returns the current hour.

or in other function I test if it the should be executed. it enables the execution of the rest of the function only in interval 9:00 to 10:00

    void susCalibLoop() {

      const byte SUSCALIB_HOUR = 9;
      static boolean done = false;

      int hourNow = hour(now());

      if (hourNow != SUSCALIB_HOUR) {
        if (done) {
          done = false;
        }
        return;
      }
      if (done)
        return;
    ...


body:
For time-keeping on a long-term basis, you are going to run up against clock drift and offsets from tick-tracking. You may be better off using a real-time-clock (RTC) such as the [DS1307][1]. This and RTCs like it are often available in breakout boards with a coin-cell battery holder built in.

You would still get the time from your HTTP or NTP source, but the RTC will be much better at keeping the "right" time as you would expect a wristwatch or desk clock to do, versus using the MCU for counting milliseconds.

You can use Ticks or `millis()` to set up a periodic read of the RTC every second or every 10 seconds, etc. Avoid using the MCU clock for long-term real-world time keeping.

  [1]: https://datasheets.maximintegrated.com/en/ds/DS1307.pdf


message:
Do You Put a Break after the Last case in a Switch?

The [Arduino Switch Case Reference][1] has a switch structure written two different ways:

First in the Syntax as:

    switch (var) {
      case label1:
        // statements
        break;
      case label2:
        // statements
        break;
      default:
        // statements
    }

and then in the Example code as:

      switch (var) {
        case 1:
          //do something when var equals 1
          break;
        case 2:
          //do something when var equals 2
          break;
        default:
          // if nothing else matches, do the default
          // default is optional
          break;
      }

Is there any reason to (or not to) add a `break;` in the `default:` case? Does the need for 'break;' change if the final case is not `default:`?

  [1]: https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

body:
You can, but you don't have to.

Should you? That's up to you.

I do. That's because it's then simple to add another `case` at the end of the structure in the future if you want, and you don't have to remember to add the `break` to the existing last case.


message:
How to upload program to custom arduino board without USB FTDI and making it read only?

If I was to mass produce a microcontroller board I have designed based around the atmega328 (very similar to an arduino uno) but for one embedded task where I want one program only to be stored on it. I want to make the program read only and impossible to access and impossible to overwrite. The board will not include a USB FTDI chip in order to prevent another program being uploaded via arduino IDE. How would I upload said program to the microcontroller?

Would I have to make use of ICSP pins (I dont know much about that) and if this is an impossible task and so a USB will have to be integrated to upload programs... How would i prevent other programs overwriting the main program and also prevent this program from being viewed?
[The main program is written in the arduino IDE]

body:
I think you cannot prevent overwriting the firmware, neither prevent viewed by others.

However, you can detect that someone overwrites it (besides you), by reading some code from e.g. EEPROM based on the content of your firmware. If you read a different code, than you can act upon it.


message:
NOT realtime MP3 decoder

I know that MP3 is the most popular audio format out there, but I need to be able to convert them to wav files for bother project I'm working on. It can be done with a PC but I would like to know if there is a way of decoding a MP3 file and turning it into a pcm wav file on an Arduino. I don't want to use an extra chip, as I do not plan on playing the MP3s, just converting them.

body:
The mp3 audio coding is not just one mathematical calculation. To decode every mp3 file you need a complete package and enough memory. That is not something for a simple arduino board.

There are libraries to decode for example a jpg file or a mp3 file. They have restrictions and you need a faster processor.
Adafruit has made a start: [https://learn.adafruit.com/native-mp3-decoding-on-arduino/][1], but you need a powerful non-standaard arduino-compatible board. That library does not use I2S yet.

I suggest to use a Raspberry Pi.

  [1]: https://learn.adafruit.com/native-mp3-decoding-on-arduino/


message:
Arduino Yun can no longer send to Dropbox

A long time ago I had set up an Arduino Yun to send files to Dropbox... I tried now and it ends in "killed" when trying to install the latest Dropbox Python module.

`pip install (six, urllib3, etc etc)` does work individually without running out of memory. Unfortunately when I install all but Dropbox, and then put the Dropbox module code folder in the current directory, it does start to import Dropbox with `import dropbox` but ends up with the KILLED message.

Is there a way I can connect to my current Dropbox without it using all of the 60mb of RAM and quitting... I keep getting the error with version 2.1:

>Error.Cannot connect to Dropbox
[400] u'v1_retired'

body: I'd eventually figured out how to do it running the latest Dropbox module installed into the sd card where there was room.


message:
Problem with serial connection. Data garbled

I have a hardware device that sends data over the serial port and over a socket connection.

I have the TX of the device connected to the RX of the ESP8266, RX of the device to TX of the ESP8266.

Comm speed is set to 115200 on both.

Code is nothing more than

    void setup() {
      // Open serial communications and wait for port to open:
      Serial.begin(115200);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    }

    void loop() { // run over and over
      if (Serial.available()) {
        Serial.write(Serial.read());
      }
    }

I listen on the socket and on the serial port at the same time. On the socket port i get correct data (ASCII characters). On the serial monitor of the Arduino i get garbled data. Also, it looks like the Arduino IDE cannot cope with the volume of data. I am sending appx 100 char/sec.

Any ideas?

**Update Aug 13 '18**

Ok, I found out that I was trying to hook up an RS232 to an UART and that, to accomplish this, I need a RS232 to TTL converter like the max3232. I will go that road and update the question if I have it.

---

Ok, i found out that i was trying to hook up an RS232 to an UART and that, to accomplish this, i need a RS232 to TTL converter like the max3232.
I will go that road and update the question if i have it.

body:
I think RS232 signals are outside the TTL limits; I don't know if you've done any permanent damage.

On the interfacing itself:

https://www.sparkfun.com/tutorials/215

On the damage part:

https://forum.arduino.cc/index.php?topic=26139.0


message:
String & Char concatenations

A newbie in Arduino- and I'm trying to concatenate string and chars ( well in python it is quite different ).

I'm trying to post a MQTT message- constructed following format to the `client.publish(outTopic, "["+outTopic+"]"+ msg)`

while `outTopic` is a char* variable, and `msg` is char- but I get an error for such concatenation.

please your help

    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>

    // GPIOs on SONOFF board
    int LED_SONOFF = 13;
    int REL_SONOFF = 12;
    int PIN_SW = 14;

    const char* ssid = "HomeNetwork_2.4G";
    const char* password = "pswd";
    const char* mqtt_server = "192.168.2.113";

    WiFiClient espClient;
    PubSubClient client(espClient);

    char msg[50];
    const char* outTopic = "HomePi/Dvir/Messages";
    const char* inTopic = "HomePi/Dvir/Windows/SONOFF";
    const char* inTopic2 = "HomePi/Dvir/Windows/All";
    const char* clientID = "Sonoff#1";
    String m1, m2;

    void start_wifi() {
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);

      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    }

    void setup() {
      start_wifi(); // start wifi service
      Serial.begin(115200); // start serial service
      delay(10);

      // define sonoff gpios
      pinMode(LED_SONOFF, OUTPUT);
      pinMode(REL_SONOFF, OUTPUT);
      pinMode(PIN_SW, INPUT_PULLUP); // GPIO14 has a pullup resistor
      digitalWrite(LED_SONOFF,HIGH); // LED high is OFF
      digitalWrite(REL_SONOFF,LOW);

      // start mqtt
      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);
    }

    void switch_on() {
      digitalWrite(REL_SONOFF,HIGH);
      digitalWrite(LED_SONOFF, LOW); // LED ON
      pub_mqtt("Switch ON");
    }

    void switch_off() {
      digitalWrite(REL_SONOFF,LOW);
      digitalWrite(LED_SONOFF, HIGH); // LED OFF
      pub_mqtt("Switch OFF");
    }

    void callback(char* topic, byte* payload, unsigned int length) {
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      Serial.println();

      if ((char)payload[0] == '1') {
        switch_on();
      }
      if ((char)payload[0] == '0') {
        switch_off();
        Serial.print("payload: ");
        Serial.println(payload[0]);
      }

    }

    void reconnect() {
      while (!client.connected()) {
        Serial.print("Attempting MQTT connection...");
        if (client.connect("ESP8266Client")) {
          Serial.println("connected");
          client.publish(outTopic, "Connected");

          client.subscribe(inTopic);
          m1="Subscribed to: "+inTopic;
          client.publish(outTopic, m1);
          if (inTopic2 !=""){
            client.subscribe(inTopic2);
            m2="Subscribed to: ";//+ String(inTopic2);
            client.publish(outTopic, m2);
          }

        } else {
          Serial.print("failed, rc=");
          Serial.print(client.state());
          Serial.println(" try again in 5 seconds");
          delay(5000);
        }
      }
    }

    void pub_mqtt(char* msg) {
      client.publish(outTopic, msg);
    }

    void loop() {
      if (!client.connected()) {
        reconnect();
      }
      client.loop();

      if (digitalRead(PIN_SW)==1) {
        if (digitalRead(REL_SONOFF)!=LOW) {
          switch_off();
        }
      }
      else if (digitalRead(PIN_SW)==0) {
        if (digitalRead(REL_SONOFF)!=HIGH){
          switch_on();
        }
      }
       delay(100);
    }

body:
You can't simply concatenate C strings like that. Instead you have to build them up into a new string.  For formatting like that the simplest way is with `sprintf`:

    char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
    sprintf(outMessage, "[%s]%s", outTopic, msg);
    client.publish(outTopic, outMessage);

Another method is with strcpy and strcat:

    char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
    strcpy(outMessage, "[");
    strcat(outMessage, outTopic);
    strcat(outMessage, "]");
    strcat(outMessage, msg);
    client.publish(outTopic, outMessage);

You have to ensure that your "holding" string `outMessage` is big enough to hold everything you want to send, *plus a terminating NULL character*, otherwise your program will crash.

Another way of creating the "holding" variable is with `alloca()`. That allocates bytes on the stack for a variable - just like `malloc()` does on the heap, but doesn't require `free()`ing because it's on the stack and is reclaimed when the function exits:

    char *outMessage = (char *)alloca(strlen(outTopic) + strlen(msg) + 3);


message:
Some Arduino components seem ridiculously cheap

My project is an Arduino-based device, packed into a box.

It will need to use Speed, Latitude, Longitude and Altitude data to log hills it detects on to an SD. On the press of a button, it will need to upload the hill data to the server via Wi-Fi.

I need the following items:

 - GPS Module + Antenna
 - WiFi Module
 - SD Module
 - Altimeter
 - microSD Card
 - Inline switch for my battery pack

The cost? Well on the Pi Hut it was £120 or so:

> GPS =
> https://thepihut.com/products/sim808-gps-gprs-gsm-shield-for-arduino =
> £42
>
> WiFi =
> https://thepihut.com/products/wifi-shield-v3-for-arduino-rpsma-802-11b-g-n
> = £54
>
> SD = https://thepihut.com/products/microsd-card-module-for-arduino =
> £6
>
> microSD Card = https://thepihut.com/products/blank-micro-sd-cards
> (4GB) = £5
>
> Altimeter =
> https://thepihut.com/products/adafruit-bmp280-i2c-or-spi-barometric-pressure-altitude-sensor
> = £10
>
>
> Switch =
> https://thepihut.com/products/adafruit-in-line-power-switch-for-2-1mm-barrel-jack
> = £2.50

On Bang Good (a really cheap online shop I discovered) it was more like £30:

> GPS =
> https://www.banggood.com/GPS-UBLOX-NEO-7N-Satellite-Positioning-Module-For-Arduino-51MCU-STM32-p-1203610.html?rmmds=cart_middle_products&cur_warehouse=CN
> = £10.54
>
> GPS Antenna =
> https://www.banggood.com/GPS-Active-Ceramic-Antenna-IPX-IPEX-Interface-For-GPS-Module-p-1203537.html?rmmds=cart_middle_products&cur_warehouse=CN
> = £2.11
>
> WiFi = https://www.banggood.com/Upgraded-Version-1M-Flash-ESP8266-ESP-01-WIFI-Transceiver-Wireless-Module-p-979509.html?rmmds=cart_middle_products
> = £2.53
>
> SD = https://www.banggood.com/Micro-SD-TF-Card-Memory-Shield-Module-SPI-Mciro-SD-Adapter-For-Arduino-p-919914.html?rmmds=cart_middle_products&cur_warehouse=CN
> = £1.02
>
> microSD Card = https://www.banggood.com/4GB-MicroSD-Card-with-Card-Reader-for-RC-FPV-Camera-Quadcopter-p-1050069.html?rmmds=cart_middle_products&cur_warehouse=CN
> = £3.96
>
> Altimeter = https://www.banggood.com/MPL3115A2-IIC-I2C-Intelligent-Temperature-Pressure-Altitude-Sensor-V2_0-For-Arduino-p-1198222.html?rmmds=cart_middle_products
> = £5.16
>
> Switch = https://thepihut.com/products/adafruit-in-line-power-switch-for-2-1mm-barrel-jack
>
> = £2.50 (From Pi Hut, though)

I'm suspicious. I might be inexperienced, and this may be a bad question, but is the cheaper option lower in quality? Is the expensive one over the top? The cheap version really seems to good to be true.

body:
If something is too good to be true, it usually is.

In all seriousness, going with a reputable shop (Adafruit, Sparkfun, Pololu) can save you a bit of headaches later, especially if you are doing integration.  You might ask (email) the Pi Hut folks why you should buy from their place, rather than the other place, I'm curious what they would say.  I don't think this needs to be an accusatory sort of email (how dare you charge more!), but more of a "I see there is a price difference; obviously, something is going on which I don't know about, can you explain this?"

I've bought cheap stuff from Amazon (Arduino clones), and they'd work... after a fashion.  Bad solder masks, badly soldered components; all would make getting things going a real pain. Sometimes, a component (like a voltage regulator) wouldn't work, and so an Arduino clone would work when plugged in to a USB port, but not in a standalone mode.   Then again, this was a 4 for $10, vs 1 for $15, so it was a bit of a lark, but there was a build quality

If you are putting a lot of effort into the software for this, or paying someone for the software to be developed, or this experiment will be a costly one, the price difference wouldn't be as much of an issue.  Is £90

How many of these are you building, BTW?  If you are building many, cheaper components might be an issue.

Someone might have another take here; the other shop might be quite reputable, but you have to ask why there is a huge disparity in costs, yes.

If you are wanting to sell stuff online, people may ask for warranties, or expect something to work for N months/years; what would happen if these units fail?


body:
The cheaper option is not always lower in quality. You can find items for sale on Amazon, Ebay and Aliexpress that all have the same "seller name" and a identical picture of the item. The price is usually 5 to 10 times higher on Amazon than Ebay. Aliexpress is usually the cheapest.

During the past year, I've ordered over 100 Arduino related sensors/modules from Ebay and Aliexpress. Four from Ebay and one from Aliexpress were defective. I got a refund for all five items.

If you are going to buy the cheaper products, it's a good idea to order more than you need in case one is defective.

Some items should not be sold at any price. For example, I purchased a DHT11 temperature and humidity sensor when I first started with Arduinos. It's an inaccurate piece of garbage, and that's exactly where it went.


body:
The main reason that some devices on eBay, or where ever, are markedly cheaper is that they are *clones* produced by a third party, using designs that have been copied/pirated or reverse engineered.

This reduces the third party's set up costs, quality assurance (QA) (i.e. testing) costs and research and development (R&D) costs to almost zero (compared to those of the original manufacturer).

So, *generally*, the board will, for all intents and purposes, be the same physically, just at a much lower cost, and, as dandavis states in [his comment][1], probably with the same reliability and quality.

However, if you purchase these clones, then the research and development aren't being paid for and may inhibit further growth in the market.

In addition, sometimes the cost is reduced *even* further as the third party cloner will use inferior and cheaper, alternative, components which *may* cause the device to fail sooner than the original. They may even come from *the same factory* and be devices that are using the original components, but which have failed the QA process, for one reason or another... and then fail in extreme circumstances.

So, in summary, you are taking a gamble (albeit a small one), and whilst generally you will end up with a device of the same quality, you *may* sometimes end up with a bit of a lemon.

  [1]: https://arduino.stackexchange.com/questions/55214/some-arduino-components-seem-ridiculously-cheap#comment116329_55214


body:
I designed a battery backup power supply for a product at my work. I included the INA219 current/voltage measurement chip. For the prototype run I bought that part from two Aliexpress sellers since the cost was half of what it would cost through our normal distributors. (two orders of 50) Half of the chips we way out of spec. Some would read current okay but the voltage was off. Some the voltage was okay and the current was off. I suspect one order of the 50 was badly out of spec parts but since we didn't track which chips ended up in which boards we didn't know which was the bad batch.

In another case, we had been using a cheap buck converter (dc-dc power supply) normally called Mini360. It was a very good module and the chip was from a major IC manufacture. It was cheaper for us to buy the module than to buy the parts so I included it as a through hole component in some of my designs. A couple of months ago we had experienced some problems with a product and I then found that the Mini360 modules we were using was different. The pcb was different, a tiny bit smaller, and the switching regulator use was from a China manufacture. It was a knock-off of the original chip on the earlier Mini360. Because of what we were doing in our product, the new knock-off part caused problems for one of the designs. The part does the same job as the original part, but it wasn't the same. And how it worked for us, in one specific product, meant that I couldn't use it. On the next revision of the product I designed out the module and implemented the module onto our smd board. And we buy the original part from our normal distributors, not China. It costs us more but we need reliability.

For my hobby I use the Arduino framework as it was easier for coding. (I'm a hardware designer) I also use cheap available parts targetted for the Arduino user base. Most of the stuff is decent, good enough. But there always is a higher level of risk when we buy these cheap parts.


message:
Difference in pinout (types?) Uno/Mega

As a hands-on guy, I've started my first ever Arduino project 5 hours ago with no prior knowledge about Arduinos (I have coding experience tho. included this in case I am missing something obvious to the veterans around here). So far I have been able to hook-up 3 SSD1306 SPI OLED displays to my Uno, and created a script that allows me to control each display separately. Because my goal is to have 5 displays work off one Arduino, I figured to pin everything over to my Mega since it has more outputs (not sure yet about the differences between DIGITAL PWM on the Uno, and the 53 additional DIGITAL pins on the Mega).

First problem I encountered is that I couldn't find where the clock pulse was specified in the demo script. It's pinned on the Uno on pin 13, but this is not specified somewhere in that script, and I think once I understand the differences in pins from both boards, I might be able to help myself a few more steps into the future.

So to sum up my questions.

1. How or where is the ClockPulse being specified.
2. Can I use the 53 DIGITAL pins on the Mega, instead of the 13 DIGITAL PMW that I have on my Uno, and if yes, do I need to change some settings?

Here is my current script that works on my Uno, but not on my Mega, even if I use the same DIGITAL PMW pins on my Mega.

    #include "HCuOLED.h"
    #include "SPI.h"

    //#define CS_DI 10
    //#define DC_DI 9
    //#define RST_DI 8

    //HCuOLED HCuOLED_1(SSD1307, CS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
    HCuOLED HCuOLED_1(SSD1307, 10, 9, 8); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
    HCuOLED HCuOLED_2(SSD1307, 7, 6, 5); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
    HCuOLED HCuOLED_3(SSD1307, 4, 3, 2); // For SSD1307 displays (HCMODU0050 & HCMODU0052)

    void setup()
    {
      HCuOLED_1.Reset();
      HCuOLED_2.Reset();
      HCuOLED_3.Reset();
    }

    void loop()
    {
      //display 1
      HCuOLED_1.SetFont(Terminal_8pt);
      HCuOLED_1.Cursor(44,0);
      HCuOLED_1.Print("Cpt");
      HCuOLED_1.Cursor(20,10);
      HCuOLED_1.Print("Fastlane");

      HCuOLED_1.Cursor(14,24);
      HCuOLED_1.SetFont(LCDLarge_24pt);
      HCuOLED_1.Print("KM/H");
      HCuOLED_1.Refresh();

      HCuOLED_1.ClearBuffer();

      //display 2
      HCuOLED_2.SetFont(Terminal_8pt);
      HCuOLED_2.Cursor(44,0);
      HCuOLED_2.Print("Cpt");
      HCuOLED_2.Cursor(20,10);
      HCuOLED_2.Print("Fastlane");

      HCuOLED_2.Cursor(14,24);
      HCuOLED_2.SetFont(LCDLarge_24pt);
      HCuOLED_2.Print("RPM");
      HCuOLED_2.Refresh();

      HCuOLED_2.ClearBuffer();

      //display 3
      HCuOLED_3.SetFont(Terminal_8pt);
      HCuOLED_3.Cursor(44,0);
      HCuOLED_3.Print("Cpt");
      HCuOLED_3.Cursor(20,10);
      HCuOLED_3.Print("Fastlane");

      HCuOLED_3.Cursor(14,24);
      HCuOLED_3.SetFont(LCDLarge_24pt);
      HCuOLED_3.Print("Info");
      HCuOLED_3.Refresh();

      HCuOLED_3.ClearBuffer();
    }

And here is the original script:

    #include "HCuOLED.h"
    #include "SPI.h"

    /* Example bitmap */
    const PROGMEM byte Tiny_Logo_Resistor[] =
    {
      0xC0, 0xE0, 0x30, 0x30, 0xF0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x38, 0x0E, 0x07, 0x1E, 0x78, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x70, 0x1C, 0x07, 0x0F, 0x3C, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x3C, 0x0F, 0x07, 0x1C, 0x70, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x78, 0x1E, 0x07, 0x0E, 0x38, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF0, 0x30, 0x30, 0xE0, 0xC0,
      0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x3C, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1E, 0x38, 0x1C, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1C, 0x38, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x3C, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00,
    };

    /* Digital pin number for the displays chip select pin */
    #define CS_DI 10
    /* Digital pin number for the displays data/command pin */
    #define DC_DI 9
    /* Digital pin number for the displays reset pin */
    #define RST_DI 8

    /* Array indexes for the X and Y coordinates */
    #define X1 0
    #define Y1 1
    #define X2 2
    #define Y2 3

    /* Arrays to store coordinates and direction for the line, rectangle and bitmap */
    byte Box[4] = {1,1,20,20};
    byte BoxDir[4] = {1,1,1,1};
    byte Line[4] = {100,25,120,55};
    byte LineDir[4] = {-1,-1,-1,-1};
    byte Bitmap[2] = {40,40};
    byte BitmapDir[2] = {-1,-1};

    /* Create an instance of the library (uncomment one of the lines below) */
    //HCuOLED HCuOLED(SSD1307, SS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
    HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // For SH1106 displays (HCMODU0058 & HCMODU0059)

    void setup()
    {

      /* Reset the display */
      HCuOLED.Reset();
    }

    void loop()
    {
      /* Display some text using a small 8x8 fixed width font */
      HCuOLED.SetFont(Terminal_8pt);
      HCuOLED.Cursor(44,0);
      HCuOLED.Print("HOBBY");
      HCuOLED.Cursor(20,10);
      HCuOLED.Print("COMPONENTS");

      /* Display a number using a large 4 line LCD style font */
      HCuOLED.Cursor(20,24);
      HCuOLED.SetFont(LCDLarge_24pt);
      HCuOLED.Print("HCuOLED");

      /* Change the draw mode from NORMAL to INVERT */
      HCuOLED.DrawMode(INVERT);
      while(1)
      {
        /* Move the positions of the 3 objects */
        MoveRect();
        MoveLine();
        MoveBitmap();

        /* Draw the objects to the display buffer */
        HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
        HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

        HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
        HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);

        /* Write the display buffer to the screen */
        HCuOLED.Refresh();

        /* Draw the objects again. As we are in INVERT mode this will remove them */
        HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
        HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

        HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
        HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);
      }
    }

    /* Update the X and Y coordinates for the box */
    void MoveRect(void)
    {
      if(Box[X1] == 0 || Box[X1] == 127)
        BoxDir[X1] *= -1;
      Box[X1] += BoxDir[X1];

      if(Box[Y1] == 0 || Box[Y1] == 63)
        BoxDir[Y1] *= -1;
      Box[Y1] += BoxDir[Y1];

      if(Box[X2] == 0 || Box[X2] == 127)
        BoxDir[X2] *= -1;
      Box[X2] += BoxDir[X2];

      if(Box[Y2] == 0 || Box[Y2] == 63)
        BoxDir[Y2] *= -1;
      Box[Y2] += BoxDir[Y2];
    }

    /* Update the X and Y coordinates for the Line */
    void MoveLine(void)
    {
      if(Line[X1] == 0 || Line[X1] == 127)
        LineDir[X1] *= -1;
      Line[X1] += LineDir[X1];

      if(Line[Y1] == 0 || Line[Y1] == 63)
        LineDir[Y1] *= -1;
      Line[Y1] += LineDir[Y1];

      if(Line[X2] == 0 || Line[X2] == 127)
        LineDir[X2] *= -1;
      Line[X2] += LineDir[X2];

      if(Line[Y2] == 0 || Line[Y2] == 63)
        LineDir[Y2] *= -1;
      Line[Y2] += LineDir[Y2];
    }

    /* Update the X and Y coordinates for the bitmap */
    void MoveBitmap(void)
    {
      if(Bitmap[X1] == 0 || Bitmap[X1] == 43)
        BitmapDir[X1] *= -1;
      Bitmap[X1] += BitmapDir[X1];

      if(Bitmap[Y1] == 0 || Bitmap[Y1] == 47)
        BitmapDir[Y1] *= -1;
      Bitmap[Y1] += BitmapDir[Y1];
    }

body:
You are communicating with your OLED displays using *SPI* - Serial Peripheral Interface.  This is a special hardware peripheral built in to the MCU, and the outputs of it are physically connected inside the MCU to what become pins 11-13 on the Arduino UNO.

This, and other things like the UART, PWM and the analog inputs, are known as *alternate functions* of the pins.

On small MCUs like the Arduino uses these functions are fixed in hardware (more advanced MCUs employ a system to allow you to map the functions to different pins).

When you use SPI on the UNO it always uses pins 11-13 (MOSI, MISO and SCK in that order).  When you use SPI on the Mega it always uses pins 51, 50 and 52 (in that order for the same functions). You can't change it. Pin 10 on the UNO is the Slave Select pin, and that again is an *alternate function* which is hard wired. On the mega that function is pin 53.

For SPI to work as a master (which is what you want) then pin 10 on the UNO or pin 53 on the Mega must be set to OUTPUT. It doesn't matter if you actually use it, but it has to be set to OUTPUT as that defines the direction the SPI peripheral operates in.

So for the Mega you would wire your OLED displays to pins 51, 50 and 52 instead of pins 11, 12 and 13. You *could* use pin 53 as one of your chip select pins (though you don't *have* to, just as long as you set it to OUTPUT).

Incidentally, you can save pins on your setup by sharing some of them.  The only pin that need to be unique for each OLED is the Chip Select pin. That is the pin that tells the OLED that it is being spoken to. Only when that pin is active will the OLED listen to any of the other pins.

The only other one you may need to connect separately is the reset pins, since you reset the displays in turn - resetting the second would reset the first and undo the configuration. TBH I'd connect the RESET pins of the OLEDs to a single pin, and specify another (unused, or non-existent) pin in the constructors for RESET - then manually reset all the OLEDs together through the one LOW pulse of the RESET pin, and then call the reset functions for each display, which should configure them all.

That way you are then using just (example UNO pins numbers shown):

 * MOSI  (11)
 * MISO  (12)
 * SCK   (13)
 * DC    (7)
 * RESET (6)
 * CS1   (10)
 * CS2   (9)
 * CS3   (8)


message:
Arduino sketch- How to add Time Stamp for outgoing MQTT

I'm writing a sketch in order to upload to a Sonoff device ( Remote relay, based ESP8266 ).

All is working great, but I wish my MQTT pubs to contain following format:

`[ DATE & TIME ] msg`

ESP8266 is connected to the internet.
I;m looking for a way doing it (including periodic time updates ) without running all 1MB memory, meaning: a code that
1) get time from external source (LAN or WAN )
2) update it every 24h
3) Lite code ?

Thanks

body:
Start with the ESP8266WiFi "[NTPClient](https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino)" example.  That will teach you how you can get the "Unix Epoch" time from the internet.

That value can be fed directly into [TimeLib](https://github.com/PaulStoffregen/Time) to keep track of the time for you (indeed, TimeLib includes an [NTP example for Arduino Ethernet](https://github.com/PaulStoffregen/Time/blob/master/examples/TimeNTP/TimeNTP.ino) that should help you get started).  Do that periodically (daily, hourly, whatever), and you have your time.  TimeLib can then give you the date and time as individual components (hours, minutes, etc), which you can then construct together (I'd use `snprintf`) to include in your MQTT message:

    int len = strlen(message) + 25;
    char mqttMessage[len];
    snprintf(mqttMessage, len, "[d/d/d d:d:d] %s",
        year(), month(), day(), hour(), minute(), second(), message);

    mqttMessage => "[2018/08/11 20:36:24] foo"


message:
How do I read addresses on multiple DS2413 1-Wire GPIO Breakouts, using the Adafruit sketch?

I am using three DS2413 1-Wire GPIO Breakouts from Adafruit connected to an ESP8266.  I tested the DS2413
 breakouts using their example sketch and it works fine for just one DS2413.  But I cannot get it to work when 2 or more DS2413s are connected.

**Adafruit DS2413 Example Sketch**
 https://github.com/adafruit/Adafruit_DS2413/blob/master/DS2413.pde

**Adafruit DS2413 Overview**
https://learn.adafruit.com/adafruit-1-wire-gpio-breakout-ds2413?view=all

When I connect 2 or more DS2413s, it only blinks the LEDs connected to the 1st breakout and doesn't read the other addresses.

I made some changes to the void setup section and now I am getting the following in the serial monitor. It sees all the addresses, but it is duplicating them and the first set have "No device found on the bus!" at the end. How can I get the sketch to read all the addresses without these errors?

**Serial monitor**

    Looking for a DS2413 on the bus
    3A B2 C2 39 00 00 00 8C No device found on the bus!
    3A 8E AE 39 00 00 00 2C No device found on the bus!
    3A E5 B6 39 00 00 00 55 No device found on the bus!
    Found a DS2413: 3A B2 C2 39 00 00 00 8C
    Found a DS2413: 3A 8E AE 39 00 00 00 2C
    Found a DS2413: 3A E5 B6 39 00 00 00 55

Here is what the code with my changes.

    #include <OneWire.h>

    #define DS2413_ONEWIRE_PIN  (4)

    #define DS2413_FAMILY_ID    0x3A
    #define DS2413_ACCESS_READ  0xF5
    #define DS2413_ACCESS_WRITE 0x5A
    #define DS2413_ACK_SUCCESS  0xAA
    #define DS2413_ACK_ERROR    0xFF

    OneWire oneWire(DS2413_ONEWIRE_PIN);
    uint8_t address[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

    void printBytes(uint8_t* addr, uint8_t count, bool newline=0)
    {
      for (uint8_t i = 0; i < count; i++)
      {
        Serial.print(addr[i]>>4, HEX);
        Serial.print(addr[i]&0x0f, HEX);
        Serial.print(" ");
      }
      if (newline)
      {
        Serial.println();
      }
    }

    byte read(void)
    {
      bool ok = false;
      uint8_t results;

      oneWire.reset();
      oneWire.select(address);
      oneWire.write(DS2413_ACCESS_READ);

      results = oneWire.read();                 /* Get the register results   */
      ok = (!results & 0x0F) == (results >> 4); /* Compare nibbles            */
      results &= 0x0F;                          /* Clear inverted values      */

      oneWire.reset();

      // return ok ? results : -1;
      return results;
    }

    bool write(uint8_t state)
    {
      uint8_t ack = 0;

      /* Top six bits must '1' */
      state |= 0xFC;

      oneWire.reset();
      oneWire.select(address);
      oneWire.write(DS2413_ACCESS_WRITE);
      oneWire.write(state);
      oneWire.write(~state);                    /* Invert data and resend     */
      ack = oneWire.read();                     /* 0xAA=success, 0xFF=failure */
      if (ack == DS2413_ACK_SUCCESS)
      {
        oneWire.read();                          /* Read the status byte      */
      }
      oneWire.reset();

      return (ack == DS2413_ACK_SUCCESS ? true : false);
    }

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

      Serial.println(F("Looking for a DS2413 on the bus"));

      /* Try to find a device on the bus */
      oneWire.reset_search();
      delay(250);
      while (oneWire.search(address)) {
           printBytes(address, 8);
           Serial.println(F("No device found on the bus!"));
    }
      /* Check the CRC in the device address */
      if (OneWire::crc8(address, 7) != address[7])
      {
        Serial.println(F("Invalid CRC!"));
        return;
      }

      /* Make sure we have a DS2413 */
      if (address[0] != DS2413_FAMILY_ID)
      {
        printBytes(address, 8);
        Serial.println(F(" is not a DS2413!"));
        return;
      }

      while (oneWire.search(address)) {
      Serial.print(F("Found a DS2413: "));
      printBytes(address, 8);
      Serial.println(F(""));
    }
    }

    void loop(void)
    {
      /* Read */
      /*
      uint8_t state = read();
      if (state == -1)
        Serial.println(F("Failed reading the DS2413"));
      else
        Serial.println(state, BIN);
      */

      /* Write */
      bool ok = false;
      ok = write(0x3);
      if (!ok) Serial.println(F("Wire failed"));
      delay(1000);
      ok = write(0x0);
      if (!ok) Serial.println(F("Wire failed"));
      delay(1000);
    }

body:
You have two detection loop in your setup function.
This one can be safely deleted as for each detected device it will print the error message

    while (oneWire.search(address)) {
       printBytes(address, 8);
       Serial.println(F("No device found on the bus!"));
}


body:
I was able to get the ESP8266 to read all DS2413 devices without errors as well as blink each LED connected to the DS2413, individually, down the chain.

**Here are animations of it working.**
![multiple_DS2413_blink](https://gist.github.com/orbitrod/51eb10c1a88f5747dc79298030e4480c/raw/c0737dfbb40e3a9c9a505f285515b7643cc80742/multiple_DS2413_blink.gif)
![multiple_DS2413_read](https://gist.github.com/orbitrod/51eb10c1a88f5747dc79298030e4480c/raw/c0737dfbb40e3a9c9a505f285515b7643cc80742/multiple_DS2413_read.gif)

I owe all the credit to [mortonkopf][1] on Github. His sketch [DS2413_button_array_test][2], was exactly what I needed to be able to read the addresses on all DS2413 devices connected and blink each LED. Here is a link to his OneWire_DS2413_array repo.

https://github.com/mortonkopf/OneWire_DS2413_array

  [1]: https://github.com/mortonkopf
  [2]: https://github.com/mortonkopf/OneWire_DS2413_array/blob/master/DS2413_button_array_test

**Here is the code I am using to make this work.**

    // This sketch is based on mortonkopf's DS2413_button_array_test sketch and allows
    // you to read multiple DS2413 devices and blink an LED connected to each DS2413,
    // individually, down the chain.
    // https://github.com/mortonkopf/OneWire_DS2413_array
    //
    // This sketch is an improvement on the write feature of the Adafruit DS2413
    // sketch which only reads 1 DS2413 device.
    // https://github.com/adafruit/Adafruit_DS2413
    // https://learn.adafruit.com/adafruit-1-wire-gpio-breakout-ds2413/reading-writing-and-arithmatic

    #include <OneWire.h>

    /* reading pins
    0x0 (B00000000) - Both pins LOW
    0x1 (B00000001) - IOA = HIGH, IOB = LOW
    0x2 (B00000010) - IOA = LOW, IOB = HIGH
    0x3 (B00000011) - Both pins HIGH
    0xFF (B11111111) - Read Failed!
    */
    #define DS2413_ONEWIRE_PIN  (4) // GPIO 4 on Adafruit Feather HUZZAH ESP8266

    #define DS2413_FAMILY_ID    0x3A
    #define DS2413_ACCESS_READ  0xF5
    #define DS2413_ACCESS_WRITE 0x5A
    #define DS2413_ACK_SUCCESS  0xAA
    #define DS2413_ACK_ERROR    0xFF

    #define BUTTON_NO 3 //use this for size of array to store state values//

    OneWire oneWire(DS2413_ONEWIRE_PIN);
    uint8_t address[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

    byte Button_states[BUTTON_NO];//this is the array of button states//

    void printBytes(uint8_t* addr, uint8_t count, bool newline=0)
    {
      for (uint8_t i = 0; i < count; i++)
      {
        Serial.print(addr[i]>>4, HEX);
        Serial.print(addr[i]&0x0f, HEX);
        Serial.print(" ");
      }
      if (newline)
      {
        Serial.println();
      }
    }

    byte read(void)
    {
      bool ok = false;
      uint8_t results;

      oneWire.reset();
      oneWire.select(address);
      oneWire.write(DS2413_ACCESS_READ);

      results = oneWire.read();                 /* Get the register results   */
      ok = (!results & 0x0F) == (results >> 4); /* Compare nibbles            */
      results &= 0x0F;                          /* Clear inverted values      */

      oneWire.reset();

      // return ok ? results : -1;
      return results;
    }

    bool write(uint8_t state)
    {
      uint8_t ack = 0;

      /* Top six bits must '1' */
      state |= 0xFC;

      oneWire.reset();
      oneWire.select(address);
      oneWire.write(DS2413_ACCESS_WRITE);
      oneWire.write(state);
      oneWire.write(~state);                    /* Invert data and resend     */
      ack = oneWire.read();                     /* 0xAA=success, 0xFF=failure */
      if (ack == DS2413_ACK_SUCCESS)
      {
        oneWire.read();                          /* Read the status byte      */
      }
      oneWire.reset();

      return (ack == DS2413_ACK_SUCCESS ? true : false);
    }

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

      Serial.println(F("Looking for a DS2413 on the bus"));
    }

    void loop(void) {
      byte i;
      byte present = 0;
      byte data[12];
      byte addr[8];

      if ( !oneWire.search(address)) {
        Serial.println("");
        Serial.print("No more addresses.\n");
        oneWire.reset_search();
        delay(50); //was 250
        return;
      }
      Serial.println("");
      Serial.print("R=");
      for( i = 0; i < 8; i++) {
        Serial.print(address[i], HEX);
        Serial.print(" ");
      }

      if ( OneWire::crc8( address, 7) != address[7]) {
          Serial.print("CRC is not valid!\n");
          return;
      }

      if ( address[0] != DS2413_FAMILY_ID) {
          Serial.print("Device is not a DS2413 family device.\n");
          return;
      }

    // Blink each LED connected to the DS2413 one at a time
      bool ok = false;
      ok = write(0x1);
      if (!ok) Serial.println(F("Wire failed"));
      delay(200);
      ok = write(0x2);
      if (!ok) Serial.println(F("Wire failed"));
      delay(200);
      ok = write(0x0);
      if (!ok) Serial.println(F("Wire failed"));
      delay(200);
    ///////////////////

    uint8_t state = read();
      const int IOA = 0x1;
      const int IOB = 0x2;

      if (state == -1)
      {
        Serial.println(F("Failed reading the DS2413"));
      }
      else
      {
        if (state & IOA)
        {
           Serial.print("   A");
        }
        if (state & IOB)
        { //can use this IO if needed to perfom tasks
            Serial.print("   B");
        }
      }

    }

Here is a link to the Gist I created for this sketch.
https://gist.github.com/orbitrod/51eb10c1a88f5747dc79298030e4480c


message:
How do I set a 25 kHz PWM signal on an ESP-WROOM-32?

I want to control a single pin of an ESP-WROOM-32 to have a 25 kHz PWM signal. How do I do that in Arduino Studio? I compiled a "hello world" program for such a device successfully in Arduino Studio, now what steps do I need to take? (Other libraries? Source Code?)

FYI: I'd like to do quite the same as provided in https://arduino.stackexchange.com/questions/25609/set-pwm-frequency-to-25-khz but not on an AVM micro-controller but an ESP32. There are tons of explanations for original Arduinos and ESP8266s using bit banging in various forms. But how do I do that on an ESP-WROOM-32 using no bit banging but built in PWM?

Background: I'd like to control a standard 12V PWM fan with this signal. As far as I learned I just can connect a pin with the PWM input of the fan. I just don't seem to be able to figure out how to produce such high frequent PWM signals on an ESP32 :-/ Please help!

body:
It is very simple to set up a PWM signal at any frequency you desire, with any resolution you desire, provided you don't exceed the maximum 'bandwidth': the frequency multplied by the resolution must be less than half the clock speed of the device.

The full explanation with relation to the ESP-IDF is [available here][1]. The article explains the intricacies of all the channels and their configurations. I must confess I have not read it all, because my application was very basic.

In `setup()`, the code required to instantiate a PWM signal on channel *`chan`* at frequency *`freq`*, with a resolution of *`bit_num`* bits is:

    double ledcSetup(uint8_t chan, double freq, uint8_t bit_num)

The code to attach the channel *`chan`* to an output pin *`pin`* is:

    void ledcAttachPin(uint8_t pin, uint8_t chan)

Within `loop()`, or otherwise, inflict a duty cycle *`duty`* to a given channel *`chan`* using:

    void ledcWrite(uint8_t chan, uint32_t duty)

I recommend perusing `esp32-hal-ledc.c` in the core files you installed that enabled you to program the ESP32 in Arduino Studio. You don't need to include any files to get the above functionality, but it's always good to know a bit about what goes on behind the scenes.

A few things to note, if reading through the core code is too much:

 - `chan` can only be between 0 and 15, and the function will return 0 if you try an number outside these bounds;
 -  you can't attach the PWM output to *all* of the GPIO pins, as some are input only and others might have secondary functions that you need;
 - `duty` is a 32-bit type but the maximum value is determined by the resolution you used for `bit_num`. For example, if `bit_num` is 8 then the range of `duty` is from 0 to 255. I don't know what happens if you put higher number: the duty may stay at 100%,  or the `duty` may be bitmasked such that writing 256 is the same as  0, 257 is 1, etc.

Once you have mastered this, the ESP32 includes 'fading' functionality, whereby the duty cycle changes from `x%` to `y%` in `z milliseconds`. There are a number of tutorials on the internet for such a thing.

**FINAL NOTE:**

If you haven't already, take a look at [Intel's PWM fan specs][2]. It states that you need an open-collector or open-drain source provided, in your case, by the ESP32. There's a chance that the PWM pin is pulled up to 5.25V within the fan; this will hurt the ESP32 if you just wire the two together. Likewise, the Tachometer output is pulled all the way up to 12V. This will kill the ESP32 if you wire it directly to the fan.

  [1]: https://esp-idf.readthedocs.io/en/latest/api-reference/peripherals/ledc.html#ledc-api-configure-timer "LED Control"
  [2]: https://www.hobbielektronika.hu/forum/getfile.php?id=256172 "Intel Specs"


body:
I know it is an old topic, but at the moment I'm also busy with it.

To be sure the ESP32 doesn't get to much voltage from the pwm input, you have to measure on the PWM input if the signal is not above 3V3, otherwhise you need a resistor divider or work with a transistor in between to pull the signal down. Mine is around 3V3 so I can directly connect the ESP32 to the fan, but just like you I put a serie resistor (330) in between for a bit protection. If this input is around 5.25 V and you connect it to the ESP32, it will probably not directly go broke, but this depends on the input resistance of the fan and how much current the internal protection diode can take in the ESP32.

For the tacho signal, it is very simple, just connect it with a pullup resistor (10K) to the desired voltage you want. In my case I will connect it to 3V3 because the ESP32 is working on 3V3. The fan controller pulls it down if rotating.

I use this schematic as guide,
PWM Input:
[![enter image description here][1]][1]

Tacho open collector output:

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

website:
[Fan controller][3]

Hope this helps, just as reference.

  [1]: https://i.stack.imgur.com/bmbZw.jpg
  [2]: https://i.stack.imgur.com/B0cWD.jpg
  [3]: https://www.electroschematics.com/fan-speed-controller/


message:
Arduino Uno - How to write personal data in NTAG213 using RFID-RC522

I am trying to write some data in NTAG213 sticker with this code:

    #include <SPI.h>
    #include <MFRC522.h>

    constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
    constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

    MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

    void setup() {
      Serial.begin(9600);        // Initialize serial communications with the PC
      SPI.begin();               // Init SPI bus
      mfrc522.PCD_Init();        // Init MFRC522 card
      Serial.println(F("Write personal data on a MIFARE PICC "));
    }

    void loop() {

    // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
      MFRC522::MIFARE_Key key;
      for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

      // Look for new cards
      if ( ! mfrc522.PICC_IsNewCardPresent()) {
       return;
    }

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
      return;
    }

    Serial.print(F("Card UID:"));    //Dump UID
    for (byte i = 0; i < mfrc522.uid.size; i++) {
       Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
       Serial.print(mfrc522.uid.uidByte[i], HEX);
    }
    Serial.print(F(" PICC type: "));   // Dump PICC type
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));

    byte buffer[34];
    byte block;
    MFRC522::StatusCode status;
    byte len;

     Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
     // Ask personal data: Family name
     Serial.println(F("Type Family name, ending with #"));
     len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
     for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces

     block = 1;
     //Serial.println(F("Authenticating using key A..."));
     status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("PCD_Authenticate() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
     }
     else Serial.println(F("PCD_Authenticate() success: "));

     // Write block
     status = mfrc522.MIFARE_Write(block, buffer, 16);
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("MIFARE_Write() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
     }
     else Serial.println(F("MIFARE_Write() success: "));

     block = 2;
     //Serial.println(F("Authenticating using key A..."));
     status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("PCD_Authenticate() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
     }

     // Write block
     status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("MIFARE_Write() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
     }
     else Serial.println(F("MIFARE_Write() success: "));

     // Ask personal data: First name
     Serial.println(F("Type First name, ending with #"));
     len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
     for (byte i = len; i < 20; i++) buffer[i] = ' ';     // pad with spaces

     block = 4;
     //Serial.println(F("Authenticating using key A..."));
     status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("PCD_Authenticate() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
     }

     // Write block
     status = mfrc522.MIFARE_Write(block, buffer, 16);
     if (status != MFRC522::STATUS_OK) {
       Serial.print(F("MIFARE_Write() failed: "));
       Serial.println(mfrc522.GetStatusCodeName(status));
       return;
      }
      else Serial.println(F("MIFARE_Write() success: "));

      block = 5;
      //Serial.println(F("Authenticating using key A..."));
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("PCD_Authenticate() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
       }

       // Write block
       status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
       if (status != MFRC522::STATUS_OK) {
         Serial.print(F("MIFARE_Write() failed: "));
         Serial.println(mfrc522.GetStatusCodeName(status));
         return;
       }
       else Serial.println(F("MIFARE_Write() success: "));

       Serial.println(" ");
       mfrc522.PICC_HaltA(); // Halt PICC
       mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
    }

With the tag and card included in the module (RC522) this code works fine:

[![Working code using card and tag][1]][1]

With the NTAG213 sticker the code doesn't work:

[![Non-working code using NTAG213 sticker][2]][2]

I need to write data in this stickers, how can I do that?

  [1]: https://i.stack.imgur.com/C7sXI.png "Working code using card and tag"
  [2]: https://i.stack.imgur.com/Ccj7G.png "Non-working code using NTAG213 sticker"

body:
The one that comes with RC552 is MiFare Classic 1K

And the programming running is for the same.

Ntag213 is MiFare Ultralight C, which requires different type of programming..

Try this one

    /* mifare ultralight example (25-02-2018)
     *
     *   RFID-RC522 (SPI connexion)
     *
     *   CARD RC522      Arduino (UNO)
     *     SDA  -----------  10 (Configurable, see SS_PIN constant)
     *     SCK  -----------  13
     *     MOSI -----------  11
     *     MISO -----------  12
     *     IRQ  -----------
     *     GND  -----------  GND
     *     RST  -----------  9 (onfigurable, see RST_PIN constant)
     *     3.3V ----------- 3.3V
     *
     */

      #include <SPI.h>
      #include <MFRC522.h>

      #define SS_PIN          10
      #define RST_PIN         6

      MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
      MFRC522::StatusCode status; //variable to get card status

      byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
      byte size = sizeof(buffer);

      uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                                //Ultraligth mem = 16 pages. 4 bytes per page.
                                //Pages 0 to 4 are for special functions.

    void setup() {
      Serial.begin(9600); // Initialize serial communications with the PC
      SPI.begin(); // Init SPI bus
      mfrc522.PCD_Init(); // Init MFRC522 card
      Serial.println(F("Sketch has been started!"));
      memcpy(buffer,"HELLO WORLD! ;-)",16);
    }

    void loop() {
      // Look for new cards
      if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

      // Select one of the cards
      if ( ! mfrc522.PICC_ReadCardSerial())
        return;

      // Write data ***********************************************

      for (int i=0; i < 4; i++) {
        //data is writen in blocks of 4 bytes (4 bytes per page)
        status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer[i*4], 4);
        if (status != MFRC522::STATUS_OK) {
          Serial.print(F("MIFARE_Read() failed: "));
          Serial.println(mfrc522.GetStatusCodeName(status));
          return;
        }
      }
      Serial.println(F("MIFARE_Ultralight_Write() OK "));
      Serial.println();

      // Read data ***************************************************
      Serial.println(F("Reading data ... "));
      //data in 4 block is readed at once.
      status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
      if (status != MFRC522::STATUS_OK) {
        Serial.print(F("MIFARE_Read() failed: "));
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }

      Serial.print(F("Readed data: "));
      //Dump a byte array to Serial
      for (byte i = 0; i < 16; i++) {
        Serial.write(buffer[i]);
      }
      Serial.println();

      mfrc522.PICC_HaltA();

    }


message:
Device Security - EEPROM data

I'm writing code for Arduino that I plan to distribute. But I worry about piracy (the .HEX can extracted from the board and reuploaded to another).

With that in mind, I am storing data to the EEPROM.

Since I am storing data to the EEPROM, can the data be extracted in some way?

body:
Nothing is 100% secure. For example, EEPROM and flash can be read using techniques like Scanning Probe Microscopy & Scanning Electron Microscope, even if the security bit is set. IMO, the goal to safely securing your data is to make it extremely hard. You should take a look at the ATAES132a from MicroChip.

> The first device in the AES family, the ATAES132A, is a high-speed, high-security, 32K Serial EEPROM that enables authentication and confidential nonvolatile data storage

It also boast a tamper resistant hardware

> The ATAES132A device contains physical security features to prevent an attacker from determining the
internal secrets. ATAES132A includes tamper detectors for voltage, temperature, frequency, and light, as
well as an active metal shield over the circuitry, internal memory encryption, and other various features.
The ATAES132A physical design and cryptographic protocol are designed to prevent or significantly
complicate most algorithmic, timing, and side-channel attacks.


message:
NodeMCU - use flash button as input in loop()

I couldn't find a proper answer on the net so I came here as a last resort.
So I want to use the FLASH button as an input in the `loop()` method.

Is there a way the check if it's pressed or not?

[![ESP module with the flash button][1]][1]

  [1]: https://i.stack.imgur.com/FMur3.png "ESP module with the flash button"

body:
The Flash button on NodeMCU is connected between io `0` and ground.  You can use it as a button.  Set `pinMode(0, INPUT_PULLUP)` and you will read io `0` LOW if the button is pressed.

[NodeMCU schema][1]

To put the module in flashing mode, first the Flash button must be held and the Reset button pushed, only then should the Flash button be released. Normally, the reset to flashing mode is done automatically by esptool before uploading over USB. This uses the circuit connected to serial RST and DTS lines.

  [1]: https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF


body: I often use it as an input if I need a button input on my boards. After the initial boot sequence it is just another I/O pin.


body:
Just to complete the other answers, here is sample Lua code to help you get started

    inpin=3 -- Select input pin - GPIO0

    function pressed()
        print("PRG Pressed")
    end

    gpio.mode(inpin,gpio.INT,gpio.PULLUP)
    gpio.trig(inpin,"down",pressed)

When you press the "Flash" or "PRG" button "PRG Pressed" is printed. You can perform additional magic in the function.

Above sample code adapted from [this][1] blog post

I am using [this][2] board from MakerFocus

  [1]: https://esp8266-projects.org/2015/03/buttons-pushbuttons-and-debouncing-story-html/
  [2]: https://www.amazon.com/MakerFocus-ESP8266-Development-Display-Support/dp/B076JDVRLP/ref=sr_1_1_sspa?ie=UTF8&qid=1550622263&sr=8-1-spons&keywords=makerfocus oled&psc=1


body:
I recommend you EasyButton library, you can use pin 0 (D3) in NodeMCU, if you want use a external button module, you can wire your button between D3 pin and GND.

https://github.com/evert-arias/EasyButton
``` lang-js
#include <EasyButton.h>

// Arduino pin where the button is connected to.
#define BUTTON_PIN 0

// Instance of the button.
EasyButton button(BUTTON_PIN);

// Callback function to be called when the button is pressed.
void onPressed() {
 Serial.println("Button has been pressed!");
}

void setup() {
 // Initialize Serial for debuging purposes.
 Serial.begin(115200);
 // Initialize the button.
 button.begin();
 // Add the callback function to be called when the button is pressed.
 button.onPressed(onPressed);
}

void loop() {
 // Continuously read the status of the button.
 button.read();
}

```


body: The top answer only works for me when the Nodemcu is connected via a serial port and the "Serial Monitor" is turned on.  (It was frustrating because it would always work whenever I connect up the serial monitor for debugging and then stop working when I disconnect it to run standalone).   I think this is because the Nodemcu connects GPIO0 and GPIO16 to the UART's RTS and DTR signals.   The buttons only work when those control lines are in the right states and that might not always be the case.   See the third page in the schematic at https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF


message:
How to parse 20180810T143000Z to time_t

What is the shortest/most elegant way (i.e. use existing lib functions) to parse a string in the form of `20180810T143000Z` to a `time_t`? Note that the literal always represents a UTC timestamp.

I started parsing the string and assigning values to a `struct tm *tm` in order to do a `mktime(tm)` at the end. That feels overly complicated, though.

body:
    #include <Time.h>

    void setup() {

      Serial.begin(115200);

      char buff[] = "20180810T143000Z";
      for (int i = 0; i < sizeof(buff); i++) {
        buff[i] = buff[i] - '0';
      }
      int yr = buff[0] * 1000 + buff[1] * 100 + buff[2] * 10 + buff[3];
      if (yr > 99)
        yr = yr - 1970;
      else
        yr += 30;
      TimeElements tm;
      tm.Year = yr;
      tm.Month = buff[4] * 10 + buff[5];
      tm.Day = buff[6] * 10 + buff[7];
      // 8 T
      tm.Hour = buff[9] * 10 + buff[10];
      tm.Minute = buff[11] * 10 + buff[12];
      tm.Second = buff[13] * 10 + buff[14];

      time_t t = makeTime(tm);

      sprintf(buff, "ddd ddd", year(t), month(t), day(t), hour(t), minute(t), second(t));

      Serial.println(buff);

    }

    void loop() {

    }

You can install TimeLib in Library Manager. It works on all Arduino platforms.


body:
Parsing the string really is the only way. However there are many ways of doing it.

My preferred method is to first check that the format is correct, by looking for the T and Z being in the right place:

    if (timeString[8] == 'T' && timeString[15] == 'Z') {
        ... parse in here
    }

And the parsing is just making numbers with multiplication:

    int year = (timeString[0] - '0') * 1000 +
               (timeString[1] - '0') * 100 +
               (timeString[2] - '0') * 10 +
               (timeString[3] - '0');

You can clean things up with a macro if you like:

    #define NUM(off, mult) ((timeString[(off)] - '0') * (mult))

Then:

    int year =   NUM(0, 1000) + NUM(1, 100) + NUM(2, 10) + NUM(3, 1);
    int month =  NUM(4, 10)   + NUM(5, 1);
    int day =    NUM(6, 10)   + NUM(7, 1);
    int hour =   NUM(9, 10)   + NUM(10, 1);
    int minute = NUM(11, 10)  + NUM(12, 1);
    int second = NUM(13, 10)  + NUM(14, 1);

And then, yes, put them in a `struct tm` (or directly assign them calculation results without using the intermediate variables) and call `mktime()`.


body:
For the sake of completeness here's my "answer" working with `String`s rather than `char[]`.

    time_t convertToTime(String calTimestamp) {
      struct tm tm;
      Serial.println("Parsing " + calTimestamp);
      String year = calTimestamp.substring(0, 4);
      String month = calTimestamp.substring(4, 6);
      if (month.startsWith("0")) {
        month = month.substring(1);
      }
      String day = calTimestamp.substring(6, 8);
      if (day.startsWith("0")) {
        month = day.substring(1);
      }
      tm.tm_year = year.toInt() - 1900;
      tm.tm_mon = month.toInt() - 1;
      tm.tm_mday = day.toInt();
      tm.tm_hour = calTimestamp.substring(9, 11).toInt();
      tm.tm_min = calTimestamp.substring(11, 13).toInt();
      tm.tm_sec = calTimestamp.substring(13, 15).toInt();
      return mktime(&tm);
    }


body:
This is not complete without sscanf.

I took the sketch by @Juraj and declared seperate integers to be sure that every %d would match with an integer.

    #include <Time.h>

    void setup() {

      Serial.begin(115200);

      char buff[] = "20180810T143000Z";

      TimeElements tm;

      int yr, mnth, d, h, m, s;
      sscanf( buff, "M--T---Z", &yr, &mnth, &d, &h, &m, &s);

      tm.Year = yr - 1970;
      tm.Month = mnth;
      tm.Day = d;
      tm.Hour = h;
      tm.Minute = m;
      tm.Second = s;

      time_t t = makeTime(tm);

      sprintf(buff, "d-d-d d:d:d", year(t), month(t), day(t), hour(t), minute(t), second(t));

      Serial.println(buff);
    }

    void loop() {
    }

Marcel Stör, there are now four good solutions. In my opinion they are equally good.


body:
Alternative to my first answer would be to use standard C functions from time.h and sscanf. C function strptime can't parse the timestamp without delimiters. But sscanf can parse your input.

    #include <time.h>

    void setup() {

      Serial.begin(115200);

      const char* buff = "20180810T143000Z";

      tm tms;
      sscanf(buff, "dddTddd", &(tms.tm_year), &(tms.tm_mon), &(tms.tm_mday), &(tms.tm_hour), &(tms.tm_min), &(tms.tm_sec));
      tms.tm_year -= 1900;
      tms.tm_mon -= 1;
      tms.tm_isdst = 0;
      time_t t = mktime(&tms);

      Serial.println(ctime(&t));
    }

    void loop() {
    }

In AVR "hhd" must be used because the corresponding members in struct tm are int8_t.


body:
Here is yet another way to convert the time stamp string to time_t. There are several great answers here already, but you may want to compare binary file sizes. This sketch's is 3884 bytes (IDE Version 1.0.6.2, GCC 4.2.1).

    #include <Time.h>
    TimeElements myTimeElements;
    char timeString[] = "20180810T143000Z";

    void setup(){

      Serial.begin(9600);

      myTimeElements.Year = CalendarYrToTm((timeString[0] - '0') * 1000 + (timeString[1] - '0') * 100 + (timeString[2] - '0') * 10 + (timeString[3] - '0'));
      myTimeElements.Month = (timeString[4] - '0') * 10 + (timeString[5] - '0');
      myTimeElements.Day = (timeString[6] - '0') * 10 + (timeString[7] - '0');
      myTimeElements.Hour = (timeString[9] - '0') * 10 + (timeString[10] - '0');
      myTimeElements.Minute = (timeString[11] - '0') * 10 + (timeString[12] - '0');
      myTimeElements.Second = (timeString[13] - '0') * 10 + (timeString[14] - '0');

      // Assemble time elements into time_t.
      time_t t = makeTime(myTimeElements);

      // Print out the contents of "t" one "piece" at a time using the "time_t" functions.
      Serial.println(year(t));
      Serial.println(month(t));
      Serial.println(day(t));
      Serial.println(hour(t));
      Serial.println(minute(t));
      Serial.println(second(t));

    }

    void loop(){}


body:
    String datetimestr = "20180810T143000Z";
    int splitted = datetimestr.indexOf("T");
    String datestr = datetimestr.substring(0, splitted); //20180810
    String timestr = datetimestr.substring(splitted + 1, datetimestr.length() - 1); //143000