body:
I bought an arduino kit, and it came with, amongst other things, a 5v relay to control 120-220v.

The relay is only that, there is only the 5 pin relay, and it's not on a board on which one can screw in the leads

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

I was wondering how I can use it..  i.e. how do I mount it somehow (especially since the leads are metric and most perf board is standard (or vice-versa)).

I don't mind soldering the 5v control leads from the arduino, but I'm not so sure about soldering or connecting 110v straight on the relay.  i'm worried about long term longevity.

I have soldered longer leads just to be able to fit it on a board for tests, but those are tiny, and aren't safe for higher voltage/current.

Any suggestions?
Thanks, Seb.

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

title: How do I use a 5v/120v relay that is not mounted on a board

Answers: 1

body:
What I did with a similar looking 'module' (An AC/DC converter), was to use a protoboard/perfboard. Some holes fitted in the existing holes, others I drilled with a small drill.

On the back you can solder the wires you need, so for the 110V wires you might use thicker wires than for the controls.

Than if you want to make it fancy, you add some terminal blocks to connect the external wires too. Terminal blocks looks like this:

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

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


body:
I know that menus were discussed perhaps a thousand times here and everywhere. But using a ready solution is not something that I'm looking for because I know I won't learn the concept if I use them. Hence the question.

I am trying to build a simple timer with a setup menu. The timer code works so that part of the code is not a problem. The menu is an adaption of a code I found online which I understand, and for the most part, works as long as I am in level 1. My menu will have 2 levels. the structure of the menu is something like this:

Option 1: Display Timer 1

Option 2: Display Timer 2

Option 3: Reset Timer 1

Option 4: Reset Timer 2

 Option 5: Set Timer 1 Action Delay

 - Option 5.1: Delay01
 - Option 5.2: Delay02
 - Option 5.3: Delay03
 - Option 5.4: Back

Option 6: Set Timer 2 Action Delay

 - Option 6.1: Delay01
 - Option 6.2: Delay02
 - Option 6.3: Delay03
 - Option 6.4: Back

The menu will be displayed with an I2C 1602 LCD Screen, and navigation will be by way of 3 push buttons: Up, Down, and Select.

I am using a nested "switch case" statement to navigate between the menus.

So as long as I'm in level 1, everything works. the times are displayed, reset works, and all is well. The moment I go to a submenu, the first option in the submenu is selected immediately and the display shows the parent menu.

I am putting the menu code in a function, the submenu code in another function. Once the menu with a submenu is selected, it calls the submenu function.

My current code is as follows: [Note: Updated with a function to handle screen updates based on @jsotola]

    #include <LiquidCrystal_I2C.h>
    #include <Wire.h>

    #include <EEPROM.h>     //EEPROM Functions: EEPROM Module
    #include <Arduino.h>    //EEPROM Functions: for type definitions

    LiquidCrystal_I2C lcd(0x27,16,2);

    //Globals:
    int page_counter = 1 ; //To move between pages
    int page_counter_s = 1; //submenu

    int up = 2;    //Up button
    int down = 3;   //Down button
    int selection = 4;  //Select button
    int LED = 13;

    int pageCount  =  7; //Main Menu

    //Main Menu
    boolean last_up   =  LOW;
    boolean last_down   =  LOW;
    boolean last_select  =  LOW;

    boolean current_up   =  LOW;
    boolean current_down  =  LOW;
    boolean current_select =  LOW;

    boolean last_up_s     =   LOW;
    boolean last_down_s     =   LOW;

    boolean current_up_s    =   LOW;
    boolean current_down_s  =   LOW;

    String line1;
    String line2;

    //---- De-bouncing function for all buttons----//
    boolean debounce(boolean last, int pin){
      boolean current = digitalRead(pin);
      if (last != current){
        delay(5);
        current = digitalRead(pin);
      }
      return current;
    }

    //LCD Function

    void printlcd(){
     lcd.setCursor(0,0);
     lcd.print(line1);
     lcd.setCursor(0,1);
     lcd.print(line2);
    }

    //Menu Function
    void Menus(){

     current_up = debounce(last_up, up);         //Debounce for Up button
     current_down = debounce(last_down, down);   //Debounce for Down button
     current_select = debounce(last_select, selection); //Debounce for Select button
     //----Page counter function to move pages----//

      //Page Up
      if (last_up == LOW && current_up == HIGH){  //When up button is pressed
        lcd.clear();                     //When page is changed, lcd clear to print new page

       if(page_counter < pageCount){             //Page counter never higher than 3(total of pages)
        page_counter= page_counter +1;   //Page up
       }
       else{
        page_counter = pageCount;
       }
      }

      last_up = current_up;

      //Page Down
      if (last_down== LOW && current_down == HIGH){ //When down button is pressed
        lcd.clear();                     //When page is changed, lcd clear to print new page
        if(page_counter >1){              //Page counter never lower than 1 (total of pages)
        page_counter= page_counter -1;   //Page down

        }
        else{
        page_counter= 1;
       }
      }

      last_down = current_down;

    //------- Switch function to write and show what you want---//
      switch (page_counter) {

        case 1:{ //Each case is a menu option

          line1 = "Counter 01:";
          line2 = "100 Hrs";
       printlcd();
        }
        break;

        case 2:{ //Each case is a menu option
          line1 = "Counter 02:";
          line2 = "70 Hrs";
       printlcd();
        }
        break;

     case 3:{ //Each case is a menu option
          line1 = "Reset 01:";
          line2 = "";
       printlcd();

       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "Success!";
       line2 = "C01 Reset";
       printlcd();

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

       delay(3000);
       lcd.clear();

      }
        }
        break;

     case 4:{ //Each case is a menu option
          line1 = "Reset 02:";
          line2 = "";
       printlcd();

       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "Success!";
       line2 = "C02 Reset";
       printlcd();

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

       delay(3000);
       lcd.clear();

      }
        }
        break;

     case 5:{ //Each case is a menu option

      line1 = "Set 01";
      line2 = "Interval";
      printlcd();

       //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       submenu();
      }
     }
        break;

     case 6:{ //Each case is a menu option
           line1 = "Set 02";
      line2 = "Interval";
      printlcd();

       //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       submenu();
      }
     }

     case 7:{ //Each case is a menu option
      line1 = "Exit service";
      line2 = "mode";
      printlcd();

       //Action:
      if (last_select == LOW && current_select == HIGH){ //When down button is pressed

       lcd.clear();
       line1 = "Exiting";
       line2 = "Please Wait";
       printlcd();

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

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

      }//switch end

    }

    void submenu(){

     current_up_s = debounce(last_up, up);         //Debounce for Up button
     current_down_s = debounce(last_down, down);   //Debounce for Down button
     current_select = debounce(last_select, selection); //Debounce for Select button
     //----Page counter function to move pages----//

      //Page Up
      if (last_up == LOW && current_up_s == HIGH){  //When up button is pressed
        lcd.clear();                     //When page is changed, lcd clear to print new page

       if(page_counter_s < 8){             //Page counter never higher than 3(total of pages)
        page_counter_s = page_counter_s +1;   //Page up
       }
       else{
        page_counter_s = 8;
       }
      }

      last_up = current_up_s;

      //Page Down
      if (last_down == LOW && current_down_s == HIGH){ //When down button is pressed
        lcd.clear();                     //When page is changed, lcd clear to print new page
        if(page_counter >1){              //Page counter never lower than 1 (total of pages)
        page_counter_s = page_counter_s -1;   //Page down

        }
        else{
        page_counter_s = 1;
       }
      }

      last_down = current_down_s;

    //------- Switch function to write and show what you want---//
      switch (page_counter_s) {

     case 1:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "100 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";;
       line2 = "100 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 2:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "200 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "200 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 3:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "300 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "300 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 4:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "400 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "400 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 5:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "500 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "500 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 6:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "600 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "600 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 7:{ //Each case is a menu option

       line1 = "Set dealy to:";
          line2 = "700 hrs";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "New Delay:";
       line2 = "700 hrs";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

     case 8:{ //Each case is a menu option

       line1 = "Back";
          line2 = "";
       printlcd();
       //Action:
       if (last_select == LOW && current_select == HIGH){ //When down button is pressed
       lcd.clear();
       line1 = "Returning";
       line2 = "";
       printlcd();

       digitalWrite(LED,HIGH);
       delay(500);
       digitalWrite(LED,LOW);
       delay(3000);
       lcd.clear();
      }
        }
        break;

      }//switch end

    }

    void setup() {
      // put your setup code here, to run once:
      lcd.init();
      lcd.backlight();
      lcd.setCursor(0,0);
      lcd.print("Menu Test");
      delay(3000);
      lcd.clear();
    }

    void loop() {

      Menus();
    }

So, my first question is: What is going wrong with the submenu?
and my second question is: in the submenu, how do I exit back to main menu?

Any assistance will be much appreciated.

Thank You.

title: Nested "switch" statements menu

Answers: 0


body:
I am using ESP32 Ping from this page: [https://github.com/pbecchi/ESP32_ping][1]

It works fine on ESP32, no compiler error.

Because something wrong on my PC, I did fresh install Windows 10 and Arduino IDE 1.8.8.

After fresh install, ESP32 Ping doesn't work anymore.

Arduino IDE Compiler error in Ping.cpp:

    //Ping.cpp

    #include <Arduino.h>

    #include <math.h>
    #include <float.h>
    #include <signal.h>
    #include <stdint.h>
    #include <string.h>
    #include <errno.h>

    #include "ping.h"

    #include "lwip/inet_chksum.h"
    #include "lwip/ip.h"
    #include "lwip/ip4.h"
    #include "lwip/err.h"
    #include "lwip/icmp.h"
    #include "lwip/sockets.h"
    #include "lwip/sys.h"
    #include "lwip/netdb.h"
    #include "lwip/dns.h"

    static uint16_t ping_seq_num;
    static uint8_t stopped = 0;

    /*
    * Statistics
    */
    static uint32_t transmitted = 0;
    static uint32_t received = 0;
    static float min_time = 0;
    static float max_time = 0;
    static float mean_time = 0;
    static float last_mean_time = 0;
    static float var_time = 0;

    #define PING_ID 0xAFAF

    #define PING_DEFAULT_COUNT    10
    #define PING_DEFAULT_INTERVAL  1
    #define PING_DEFAULT_SIZE     32
    #define PING_DEFAULT_TIMEOUT   1

    /*
    * Helper functions
    *
    */
    static void ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len) {
     size_t i;
     size_t data_len = len - sizeof(struct icmp_echo_hdr);

     ICMPH_TYPE_SET(iecho, ICMP_ECHO);
     ICMPH_CODE_SET(iecho, 0);
     iecho->chksum = 0;
     iecho->id = PING_ID;
     iecho->seqno = htons(++ping_seq_num);

     /* fill the additional data buffer with some data */
     for (i = 0; i < data_len; i++) {
      ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
     }

     iecho->chksum = inet_chksum(iecho, len);
    }

    static err_t ping_send(int s, ip4_addr_t *addr, int size) {
     struct icmp_echo_hdr *iecho;
     struct sockaddr_in to;
     size_t ping_size = sizeof(struct icmp_echo_hdr) + size;
     int err;

     iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
     if (!iecho) {
      return ERR_MEM;
     }

     ping_prepare_echo(iecho, (uint16_t)ping_size);

     to.sin_len = sizeof(to);
     to.sin_family = AF_INET;
     inet_addr_from_ipaddr(&to.sin_addr, addr);

     if ((err = sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to)))) {
      transmitted++;
     }
     free(iecho)
     return (err ? ERR_OK : ERR_VAL);
    }

    static void ping_recv(int s) {
     char buf[64];
     int fromlen, len;
     struct sockaddr_in from;
     struct ip_hdr *iphdr;
     struct icmp_echo_hdr *iecho = NULL;
     char ipa[16];
     struct timeval begin;
     struct timeval end;
     uint64_t micros_begin;
     uint64_t micros_end;
     float elapsed;

     // Register begin time
     gettimeofday(&begin, NULL);

     // Send
     while ((len = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
      if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) {
       // Register end time
       gettimeofday(&end, NULL);

       /// Get from IP address
       ip4_addr_t fromaddr;
       inet_addr_to_ipaddr(&fromaddr, &from.sin_addr);

       strcpy(ipa, inet_ntoa(fromaddr));

       // Get echo
       iphdr = (struct ip_hdr *)buf;
       iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));

       // Print ....
       if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
        received++;

        // Get elapsed time in milliseconds
        micros_begin = begin.tv_sec * 1000000;
        micros_begin += begin.tv_usec;

        micros_end = end.tv_sec * 1000000;
        micros_end += end.tv_usec;

        elapsed = (float)(micros_end - micros_begin) / (float)1000.0;

        // Update statistics
        // Mean and variance are computed in an incremental way
        if (elapsed < min_time) {
         min_time = elapsed;
        }

        if (elapsed > max_time) {
         max_time = elapsed;
        }

        last_mean_time = mean_time;
        mean_time = (((received - 1) * mean_time) + elapsed) / received;

        if (received > 1) {
         var_time = var_time + ((elapsed - last_mean_time) * (elapsed - mean_time));
        }

        // Print ...
        log_d("%d bytes from %s: icmp_seq=%d time=%.3f ms\r\n", len, ipa,
         ntohs(iecho->seqno), elapsed
        );

        return;
       }
       else {
        // TODO
       }
      }
     }

     if (len < 0) {
      log_d("Request timeout for icmp_seq %d\r\n", ping_seq_num);
     }
    }
    /*
    static void stop_action(int i) {
     signal(i, SIG_DFL);
     stopped = 1;
    }
    +/
    /*
    * Operation functions
    *
    */
    void ping(const char *name, int count, int interval, int size, int timeout) {
     // Resolve name
     hostent * target = gethostbyname(name);
     IPAddress adr = *target->h_addr_list[0];
     if (target->h_length == 0) {
      // TODO: error not found target?????
      return;
     }
     ping_start(adr, count, interval, size, timeout);
    }
    bool ping_start(struct ping_option *ping_o) {

     return ping_start(ping_o->ip,ping_o->count,0,0,0);

    }
    bool ping_start(IPAddress adr, int count=0, int interval=0, int size=0, int timeout=0) {
    // driver_error_t *error;
     struct sockaddr_in address;
     ip4_addr_t ping_target;
     int s;
     // Get default values if argument are not provided
     if (count == 0) {
      count = PING_DEFAULT_COUNT;
     }

     if (interval == 0) {
      interval = PING_DEFAULT_INTERVAL;
     }

     if (size == 0) {
      size = PING_DEFAULT_SIZE;
     }

     if (timeout == 0) {
      timeout = PING_DEFAULT_TIMEOUT;
     }

     // Create socket
     if ((s = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
      // TODO: error
      return false;
     }

     address.sin_addr.s_addr = adr;
     ping_target.addr = address.sin_addr.s_addr;

     // Setup socket
     struct timeval tout;

     // Timeout
     tout.tv_sec = timeout;
     tout.tv_usec = 0;

     if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tout, sizeof(tout)) < 0) {
      closesocket(s);
      // TODO: error
      return false;
     }

     stopped = 0;
     transmitted = 0;
     received = 0;
     min_time = 1.E+9;// FLT_MAX;
     max_time = 0.0;
     mean_time = 0.0;
     var_time = 0.0;

     // Register signal for stop ping
     //signal(SIGINT, stop_action);

     // Begin ping ...
     char ipa[16];

     strcpy(ipa, inet_ntoa(ping_target));
     log_i("PING %s: %d data bytes\r\n",  ipa, size);

     ping_seq_num = 0;

     while ((ping_seq_num < count) && (!stopped)) {
      if (ping_send(s, &ping_target, size) == ERR_OK) {
       ping_recv(s);
      }
      delay( interval*1000L);
     }

     closesocket(s);

     log_i("%d packets transmitted, %d packets received, %.1f%% packet loss\r\n",
      transmitted,
      received,
      ((((float)transmitted - (float)received) / (float)transmitted) * 100.0)
     );

     if (received) {
      ping_resp pingresp;
      log_i("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\r\n", min_time, mean_time, max_time, sqrt(var_time / received));
      pingresp.total_count = 10;
      pingresp.timeout_count = 10;
      pingresp.total_bytes = 1;
      pingresp.total_time = mean_time;
      pingresp.ping_err = 0;
      return true;
     // ping_o->sent_function(ping_o, (uint8*)&pingresp);
     }
     return false;
    }

    bool ping_regist_recv(struct ping_option *ping_opt, ping_recv_function ping_recv)
    {
     if (ping_opt == NULL)
      return false;

     ping_opt->recv_function = ping_recv;
     return true;
    }

    bool ping_regist_sent(struct ping_option *ping_opt, ping_sent_function ping_sent)
    {
     if (ping_opt == NULL)
      return false;

     ping_opt->sent_function = ping_sent;
     return true;
    }

Arduino IDE 1.8.8. compiler stop in this line:

    inet_addr_from_ipaddr(&to.sin_addr, addr);

The error message: **'inet_addr_to_ipaddr' was not declared in this scope**

According to [this post][2], `inet_addr` need `lwip` library.

So... the conclusion: cause of this issue is broken `lwip` library.

But when ESP32 Ping working fine previously, I didn't install any separate `lwip` library. Maybe ESP32 Ping use `lwip` library from Arduino library - `#include <Arduino.h>`

But why after fresh install, ESP32 Ping doesn't work anymore?

Arduino IDE installation automatically included Arduino library. Also, I didn't change anything on Arduino Sketch & Library folder - `C:\Users\Documents\Arduino`. The folder content as the same as before fresh install.

How to fix this?

Please help...

  [1]: https://github.com/pbecchi/ESP32_ping
  [2]: https://stackoverflow.com/questions/4124074/network-programming-udp-packet

Answers: 1

body:
Done this steps:

    1. Uninstall Arduino IDE 1.8.8
    2. Delete C:\Users\AppData\Local\
    3. Rename C:\Users\Documents\Arduino into C:\Users\Documents\Arduino_OLD
    4. Restart the PC
    5. Install Arduino IDE 1.8.8
    6. Install ESP32 Core version 1.0.0 using Boards Manager

Then.... compile my sketch.

And now.... **it WORKS**....  :)  :)  :)

My previous mistake is not installing ESP32 Core version 1.0.0.

I did it by installing version 1.0.1 - the Boards Manager default version - which didn't work.

It seems some change in ESP32 Core version 1.0.1 broke ESP32 Ping library connection.


body:
I'm trying to combine two strings (strings/int) together with text in below code:

    int foo = String((char*)payload).indexOf(' ');
    int message1;
    int message2;

    message1 = String((char*)payload).substring(0, foo).toInt();
    Serial.print(message1); // Returns 1

    message2 = String((char*)payload).substring(foo + 1, length).toInt();
    Serial.print(message2); // Returns 0

    client.publish(msg, String(message1 + " " + message2).c_str(), true);
    // published value: 1 0

Instead of publishing "1 0" its publishing some weird values, what am i missing?

title: How to combine strings and text together?

Answers: 1

body:
I wouldn't use the String class, but instead use the C functions to concatenate strings (like strcat, strncat).

You can use the itoa function to convert an integer to a string, see:
> https://stackoverflow.com/questions/9655202/how-to-convert-integer-to-string-in-c

Or use the sprintf function.

These are all standard C functions which gives you complete control of the buffer sizes to use. Handy because the Arduino Uno has just 2 KB.


body:
I am new to using NodeMCU and IOT. I am testing the NodeMCU (ESP8266) so that I can connect with pubnub server. Have taken code from github but there is error saying

    'mac was not declared in this scope'

and some other error too.

Can anyone tell whats the problem?

This code is from pubnub github page - https://github.com/pubnub/arduino

Code:-

    #include <Ethernet.h>

    #include <PubNub.h>

    void setup() {
        /* For debugging, set to speed of your choice */
        Serial.begin(9600);

        /* If you use some other HW, you need to do some other
           initialization of it here... */
        Ethernet.begin();

        /* Start the Pubnub library by giving it a publish and subscribe
           keys */
        PubNub.begin(publisher key, subscriber key);
    }

    void loop() {
        /* Maintain DHCP lease. For other HW, you may need to do
           something else here, or maybe nothing at all. */
        Ethernet.maintain();

        /* Publish message. You could use `auto` here... */
        PubNonSubClient *pclient = PubNub.publish(pubchannel, "\"message\"");
        if (!pclient) return;
        PublishCracker cheez;
        cheez.read_and_parse(pclient);
        /** You're mostly interested in `outcome()`, and,
            if it's "failed", then `description()`.
        */
        Serial.print("Outcome: "); Serial.print(cheez.outcome());
        Serial.print(' '); Serial.println(cheez.to_str(cheez.outcome()));
        Serial.print("description: "); Serial.println(cheez.description());
        Serial.print("timestamp: "); Serial.println(cheez.timestamp());
        Serial.print("state: "); Serial.print(cheez.state());
        Serial.print(' '); Serial.println(cheez.to_str(cheez.state()));
        pclient->stop();

        /* Wait for news. */
        PubSubClient *sclient = PubNub.subscribe(subchannel);
        if (!sclient) return; // error
        String msg;
        SubscribeCracker ritz(sclient);
        while (!ritz.finished()) {
            ritz.get(msg);
            if (msg.length() > 0) {
                Serial.print("Received: "); Serial.println(msg);
            }
        }
        sclient->stop();

        delay(1000);
    }

    error :-
      sketch_jan17a:28:47: error: 'pubchannel' was not declared in this scope

         PubNonSubClient *pclient = PubNub.publish(pubchannel, "\"message\"");

                                                   ^

    sketch_jan17a:44:46: error: 'subchannel' was not declared in this scope

         PubSubClient *sclient = PubNub.subscribe(subchannel);

                                                  ^

    Multiple libraries were found for "Ethernet.h"
     Used: C:\Users\sultan\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\libraries\Ethernet
     Not used: C:\Program Files (x86)\Arduino\libraries\Ethernet
    exit status 1
    'mac' was not declared in this scope

title: How to find the MAC address using NodeMCU when connecting to WiFi?

Answers: 1

body: I don't believe you have an Wiznet Ethernet module connected to your NodeMcu. Ethernet library is for the Wiznet chips for wired LAN. You want to use the WiFi of the NodeMcu. For that the esp8266 core has the ESP8266WiFi library. It has the same API as other WiFi libraries based on Arduino WiFi library. So you can modify the WiFi examples of the Arduino pubnub library. Only change `#include <WiFi101.h>` to `#include <ESP8266WiFi.h>`. (And remove `#include <SPI.h>`.)


body:
I'm trying to take a sketch and turn it into a class for a library I'm making, but I'm getting compile issues.

This is not a duplicate as suggested. as i explain in the comment and my answer. Thank you all for your help - as I am new to creating libraries - figured I would attempt something correctly for a change :)

Here is the original sketch: [Gotten here][1]

    #include <ros.h>
    #include <sensor_msgs/BatteryState.h>

    #define K           0.00472199
    #define CELLS       6
    #define MAX_CELLS   12

    double cell_const[MAX_CELLS] =
    {
      1.0000,
      2.1915,
      2.6970,
      4.1111,
      4.7333,
      6.6000,
      6.6000,
      7.8293,
      8.4667,
      9.2353,
      11.0000,
      11.0000
    };

    ros::NodeHandle nh;
    sensor_msgs::BatteryState batt_state;
    ros::Publisher batteryState("battery_state", &batt_state);

    void setup()
    {
      // Initialize the ROS node.
      nh.initNode();
      nh.advertise(batteryState);

      // Populate battery parameters.
      batt_state.design_capacity = 2200;      // mAh
      batt_state.power_supply_status = 2;     // discharging
      batt_state.power_supply_health = 0;     // unknown
      batt_state.power_supply_technology = 3; // LiPo
      batt_state.present = 1;                 // battery present

      batt_state.location = "Crawler";        // unit location
      batt_state.serial_number = "ABC_0001";  // unit serial number
      batt_state.cell_voltage = new float[CELLS];

    }

    void loop()
    {
      // Battery status.
      double battVoltage = 0.0;
      double prevVoltage = 0.0;

      // Populate battery state message.
      for (int i = 0; i < CELLS; i++)
      {
         // Read raw voltage from analog pin.
        double cellVoltage = analogRead(i) * K;

        // Scale reading to full voltage.
        cellVoltage *= cell_const[i];
        double tmp = cellVoltage;

        // Isolate current cell voltage.
        cellVoltage -= prevVoltage;
        battVoltage += cellVoltage;
        prevVoltage = tmp;

        // Set current cell voltage to message.
        batt_state.cell_voltage[i] = (float)cellVoltage;

        // Check if battery is attached.
        if (batt_state.cell_voltage[i] >= 2.0)
          batt_state.present = 1;
        else
          batt_state.present = 0;
      }

      // Update battery health.
      batt_state.voltage = (float)battVoltage;

      if (batt_state.voltage > CELLS * 4.2)
        batt_state.power_supply_health = 4; // overvoltage
      else if (batt_state.voltage < CELLS * 3.0)
        batt_state.power_supply_health = 3; // dead
      else
        batt_state.power_supply_health = 1; // good

      // Publish data to ROSSERIAL.
      batteryState.publish( &batt_state );
      nh.spinOnce();
      delay(1000);

    }

Here is my header file:

    #ifndef battery_h
    #define battery_h

    #if ARDUINO >= 100
    #include "Arduino.h"
    #else
    #include "WProgram.h"
    #endif

    #include <ros.h>
    #include <sensor_msgs/BatteryState.h>

    #define K           0.00472199
    #define CELLS       6
    #define MAX_CELLS   12
    #define CRITICAL    0.30

    double cell_const[MAX_CELLS] =
    {
      1.0000, 2.1915, 2.6970, 4.1111,
      4.7333, 6.6000, 6.6000, 7.8293,
      8.4667, 9.2353, 11.0000, 11.0000
    };

    ros::NodeHandle nh;
    sensor_msgs::BatteryState batt_state;

    ros::Publisher batteryState("/battery/info", &batt_state);

    class Battery
    {
      private:
       void updateBatteryHealth();
       double battVoltage;
       double prevVoltage;
      public:
        void begin();
        void updateBatteryState();
    };

    #endif

This is my cpp file:

    #include "battery.h"

    void Battery::begin(){

      // Launch ROS node and set parameters.
      nh.initNode();

      // Setup publishers/subscribers.
      nh.advertise(batteryState);

      // Populate battery parameters.
      batt_state.design_capacity          = 2200;  // mAh
      batt_state.power_supply_status      = 2;     // discharging
      batt_state.power_supply_health      = 0;     // unknown
      batt_state.power_supply_technology  = 3;     // LiPo
      batt_state.present                  = 1;     // battery present

      batt_state.location      = "Crawler";        // unit location
      batt_state.serial_number = "ABC_0001";       // unit serial number

      batt_state.cell_voltage = new float[CELLS];  // individual cell health

    }

    void Battery::updateBatteryState() {
      battVoltage = 0.0;
      prevVoltage = 0.0;
      // Reset Power Supply Health.
      batt_state.power_supply_health = 0;
        // Populate battery state message.
      for (int i = 0; i < CELLS; i++)
      {
        // Read raw voltage from analog pin.
        double cellVoltage = analogRead(i) * K;

        // Scale reading to full voltage.
        cellVoltage *= cell_const[i];
        double tmp = cellVoltage;

        // Isolate current cell voltage.
        cellVoltage -= prevVoltage;
        battVoltage += cellVoltage;
        prevVoltage = tmp;

        // Set current cell voltage to message.
        batt_state.cell_voltage[i] = (float)cellVoltage;

        // Check if battery is attached.
        if (batt_state.cell_voltage[i] >= 2.0)
        {
          if (batt_state.cell_voltage[i] <= 3.2)
            batt_state.power_supply_health = 5; // Unspecified failure.
          batt_state.present = 1;
        }
        else{
          batt_state.present = 0;
        }
      }
    };

    void Battery::updateBatteryHealth() {
        // Update battery health.
      if (batt_state.present)
      {
        batt_state.voltage = (float)battVoltage;
        float volt = batt_state.voltage;
        float low  = 3.0 * CELLS;
        float high = 4.2 * CELLS;
        batt_state.percentage = constrain((volt - low) / (high - low), 0.0, 1.0);
      }
      else
      {
        batt_state.voltage = 0.0;
        batt_state.percentage = 0.0;
      }

      // Update power supply health if not failed.
      if (batt_state.power_supply_health == 0 && batt_state.present)
      {
        if (batt_state.voltage > CELLS * 4.2)
          batt_state.power_supply_health = 4; // overvoltage
        else if (batt_state.voltage < CELLS * 3.0)
          batt_state.power_supply_health = 3; // dead
        else
          batt_state.power_supply_health = 1; // good
      }
       // Publish data to ROSSERIAL.
      batteryState.publish( &batt_state );
      nh.spinOnce();
    };

this is the error im getting simply by calling the Battery::begin function in my main class:

    libraries/KBROSRobot/KBROSRobot.cpp.o (symbol from plugin): In function `KBROSRobot::KBROSRobot()':
    (.text+0x0): multiple definition of `nh'
    sketch/rob_test.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    libraries/KBROSRobot/KBROSRobot.cpp.o (symbol from plugin): In function `KBROSRobot::KBROSRobot()':
    (.text+0x0): multiple definition of `batt_state'
    sketch/rob_test.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    libraries/KBROSRobot/KBROSRobot.cpp.o (symbol from plugin): In function `KBROSRobot::KBROSRobot()':
    (.text+0x0): multiple definition of `batteryState'
    sketch/rob_test.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    libraries/KBROSRobot/KBROSRobot.cpp.o (symbol from plugin): In function `KBROSRobot::KBROSRobot()':
    (.text+0x0): multiple definition of `cell_const'
    sketch/rob_test.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    /var/folders/m4/lq13_j5j23qc0l2wp8dqmt4h0000gp/T//cczNyzqC.ltrans1.ltrans.o: In function `begin':
    /Users/keith.brown/Documents/Arduino/libraries/KBROSRobot/KBROSRobot.cpp:9: undefined reference to `Battery::begin()'
    collect2: error: ld returned 1 exit status
    exit status 1

  [1]: https://www.instructables.com/id/1S-6S-Battery-Voltage-Monitor-ROS/

title: Error compiling a sketch to class/library conversion

Answers: 2

body:
Don't define your global variables in the header file. Only declare them, using external linkage. Then define them in the implementation file

Header (.h):

    extern ros::NodeHandle nh;

Implementation (.cpp):

    ros::NodeHandle nh;

Try to keep usage of global variables to a minimum. If you don't need them outside of the library, declare them in the implementation file and mark them static.
Or even better: encapsulate them inside of the class.

***

The reason that you are getting these errors is because each implementation file is compiled separately. You have two implementation files that include your header file, so the header file is compiled twice. This results in two global variables with the name `nh`. During the linking stage, the linker tries to combine the compiled version of both `KBROSRobot.cpp` and `rob_test.ino.cpp` (these are called object files, `.o`). The linker has no way of knowing which variable is which, because they are both defined twice, so it throws an error.

Multiple _declarations_ are fine, because it just tells the compiler "there is a definition somewhere", and the linker will find that definition eventually. That's why the declaration with external linkage solves your problem.
Multiple _definitions_ are not allowed (in most cases).

body:
I also found that all other classes in the library have to be in the `utility` folder or the wont compile. Answering my comment above. Thank you @tttapa for your help.

Now I just have to intelligently program the robot, which is unfortunately subjective... ;)


body:
I am using an Arduino Pro Mini with a L293D H-bridge driver to drive a bi-directional motor. The system takes input from a capacitive sensor which is constantly looking for a trigger. I don't have any low power optimization in the code. I was using Arduino UNO before which lasted for one day with a 9V battery. I switched to Arduino Pro Mini for longer battery life but the battery lasted for one day in that case as well.

Can anyone please help me understand what could be the possible reason for higher power consumption than normal for Arduino Pro Mini?

Thanks in advance for your help!

Niloy

title: Short battery life concern with Arduino Pro Mini

Answers: 1

body:
A standard alkaline 9V battery has a capacity rating of around 500mAh (milliAmp-hours). That rating is probably based on a current consumption of around 10mA. However, if the current consumption is higher, the apparent capacity drops. At 100mA, most 9V batteries have a capacity rating of about 300mAh, and at 500mA current draw, the apparent capacity drops down to 170mAh.

This means, if you are drawing 100mA of current constantly, a 9V battery will last (0.3Ah / 0.1A) = 3h.

A typical Arduino pro mini will draw current at around 20mA.

    500mAh / 20mA = 20h

This is not even counting the motor and driver.

A standard alkaline AA battery has a nominal voltage of 1.5V and a capacity of about 2000mAh, and 3 of them will provide a voltage between 4.5V (fully charged `1.5V x 3`) and 2.7V (fully discharged `0.9V x 3`)

With that voltage range, you could operate the Arduino pro mini in 3.3V mode, with no linear regulator, at a reduced clock frequency, such as 8Mhz, which will reduce power consumption even more.

Being able to put the chip in power-saving mode, and periodically check for necessary activity will help even more.

See [http://www.gammon.com.au/power][1] for a description of many practical methods.

That said, the Arduino is going to be a pretty small contributor to power draw compared to a DC motor, so your overall run time will heavily depend on how often the motor is turned on.

  [1]: http://www.gammon.com.au/power


body:
I've connected four YL-69 sensors to my arduino at-mega2560 on analogs pins 0-3. This is combined with four DHT11 sensors that are in digital pins.

The DHT work fine, and I can work one YL-69 moisture sensor that gives correct readings.
But when I connected the others, the readings are just 100% for all. I'm sure I must have made a mistake in my code somewhere, just can't spot it.

I've posted the sketch I use below, and the results from serial monitor.
(BTW i added a short delay of 10ms between each reading thinking that may be the issue, but it had no effect).

**Serial Monitor:**

[![Serial Monitor][1]][1]

**Sketch:**

    #include "DHT.h"
    #include <SPI.h>        // Include SPI library (needed for the SD card)
    #include <SD.h>         // Include SD library

    File dataFile;

    #define DHTPIN0 10     // what pin we're connected to
    #define DHTPIN1 11     // what pin we're connected to
    #define DHTPIN2 12     // what pin we're connected to
    #define DHTPIN3 13     // what pin we're connected to

    // Uncomment whatever type you're using!

    #define DHTTYPE DHT11   // DHT 11
    //#define DHTTYPE DHT22   // DHT 22  (AM2302)
    //#define DHTTYPE DHT21   // DHT 21 (AM2301)

    // How to connect sensors
    // Connect pin 1 (on the left) of the sensor to +5V
    // Connect pin 2 of the sensor to whatever your DHTPIN is
    // Connect pin 4 (on the right) of the sensor to GROUND
    // Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

    DHT dht0(DHTPIN0, DHTTYPE);
    DHT dht1(DHTPIN1, DHTTYPE);
    DHT dht2(DHTPIN2, DHTTYPE);
    DHT dht3(DHTPIN3, DHTTYPE);

    int output_value ;
    int output_value1 ;
    int output_value2 ;
    int output_value3 ;
    int output_value4 ;

    unsigned long time;

    void setup() {
     Serial.begin(9600);
     while (!Serial)
        ; // wait for serial port to connect. Needed for native USB port only
      Serial.print("Initializing SD card...");
      if (!SD.begin()) {
        Serial.println("initialization failed!");
        while (1);
      }
      Serial.println("initialization done.");
     Serial.println("DHTxx test!");
     dht0.begin();
     dht1.begin();
     dht2.begin();
     dht3.begin();
     delay(2000);
    }

    uint16_t line = 1;

    void loop() {
     // Reading temperature or humidity takes about 250 milliseconds!
     // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
     float h0 = dht0.readHumidity();
     float h1 = dht1.readHumidity();
     float h2 = dht2.readHumidity();
     float h3 = dht3.readHumidity();
     float t0 = dht0.readTemperature();
     float t1 = dht1.readTemperature();
     float t2 = dht2.readTemperature();
     float t3 = dht3.readTemperature();

     dataFile = SD.open("DHT11Log.csv", FILE_WRITE);
     //  if any result below is NaN (not a number) then something went wrong!
     if (dataFile) {
       output_value= analogRead(A0);
       delay(10);
       output_value1= analogRead(A1);
       delay(10);
       output_value2= analogRead(A2);
       delay(10);
       output_value3= analogRead(A3);
       delay(10);
       output_value4= analogRead(A4);
       output_value = map(output_value,1024,0,0,100);
       output_value1 = map(output_value,1024,0,0,100);
       output_value2 = map(output_value,1024,0,0,100);
       output_value3 = map(output_value,1024,0,0,100);
       output_value4 = map(output_value,1024,0,0,100);
       Serial.print("Moisture : ");
       Serial.print(output_value);
       Serial.println("%");
       Serial.print(output_value1);
       Serial.println("%");
       Serial.print(output_value2);
       Serial.println("%");
       Serial.print(output_value3);
       Serial.println("%");
       Serial.print(output_value4);
       Serial.println("%");
       Serial.print("Humidity  : sensor 0, ");
       Serial.println(h0);
       Serial.print("  sensor 1, ");
       Serial.println(h1);
       Serial.print("  sensor 2, ");
       Serial.println(h2);
       Serial.print("  sensor 3, ");
       Serial.println(h3);
       Serial.println(" %\t");
       Serial.print("temperature  : sensor 0, ");
       Serial.println(t0);
       Serial.print("  sensor 1, ");
       Serial.println(t1);
       Serial.print("  sensor 2, ");
       Serial.println(t2);
       Serial.print("  sensor 3, ");
       Serial.println(t3);
       Serial.println(" %\t");
       dataFile.print(line++);
       dataFile.print(":    Temperature = ");
       dataFile.print(",");
       dataFile.print(t0);
       dataFile.print(",");
       dataFile.print(t1);
       dataFile.print(",");
       dataFile.print(t2);
       dataFile.print(",");
       dataFile.print(t3);
       dataFile.print(",");
       dataFile.print("°C,    Humidity = ");
       dataFile.print(",");
       dataFile.print(h0);
       dataFile.print(",");
       dataFile.print(h1);
       dataFile.print(",");
       dataFile.print(h2);
       dataFile.print(",");
       dataFile.print(h3);
       dataFile.print(",");
       dataFile.println("%");
       dataFile.print(",");
       dataFile.print("Moisture : ");
       dataFile.print(",");
       dataFile.print(output_value);
       dataFile.print(",");
       dataFile.print(output_value1);
       dataFile.print(",");
       dataFile.print(output_value2);
       dataFile.print(",");
       dataFile.print(output_value3);
       dataFile.print(",");
       dataFile.print(output_value4);
       dataFile.close();

      }
      // if the file didn't open, print an error:
      else
        Serial.println("error opening DHT11Log.txt");
        delay(10000);
    }

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

title: Issue with analog readings on Arduino atMega with YL-69 moisture sensors

Answers: 1

body:
I think that the problem is here:

    output_value = map(output_value,1024,0,0,100);
    output_value1 = map(output_value,1024,0,0,100);
    output_value2 = map(output_value,1024,0,0,100);
    output_value3 = map(output_value,1024,0,0,100);
    output_value4 = map(output_value,1024,0,0,100);

replace them with:

    output_value = map(output_value,1024,0,0,100);
    output_value1 = map(output_value1,1024,0,0,100);
    output_value2 = map(output_value2,1024,0,0,100);
    output_value3 = map(output_value3,1024,0,0,100);
    output_value4 = map(output_value4,1024,0,0,100);


body:
I would like to generate 4 square signals of different frequencies below 30 hz using timers of Arduino Mega.

I was able to generate 30.6hz signals but I have no idea how to generate lower frequencies.

Any help would be appreciated.

title: How to generate 4 square signals using Arduino Mega 2560 below 30hz using timers

Answers: 0


body:
I was using OTA to upload sketches to ESP ports I have ( around 10 ESPs).
For some time now - I'm having some kind of a trouble I would like to share, since I've read some similar topics, but all didn't work.

The problem is when trying to select `Network Port` as I did before, sometimes I see all, sometimes part, sometimes only one or two, and sometimes after selecting to one I want to upload to, it fails since it disapears from that list by the time it starts the upload.

I'm using IDE 1.8.8 on a Linux machine - same issue,

Tried on mac, using both 1.8.8 and even downgraded to 1.8.7 - and I'm getting the same issue.

What might be the cause for that ?

title: Fail using OTA - Network ports

Answers: 0


body:
[![enter image description here][1]][1]Basically, it's an Arduino project in which I am stuck. I using inputs as two sensors and LED as output, for further details and concept video had been attached. I did the wiring and everything correctly but there is something wrong with the code which I couldn't figure out. Here is the code.

I had attached a video for proper understanding.

[https://youtu.be/ZQg_xbGQNE0][2]

    const int s1 = 22;     // sensor one
    const int s2 =  23;      // sensor two
    int pot_pin = A0;
    int list[15] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 44, 45, 46}; //leds pin
    //if u want change the time delay
    int timer = 1000;

    bool flag1 = false;
    void setup() {
      // initialize the pushbutton pin as an input:
      pinMode(s1, INPUT);
      pinMode(s1, INPUT);
      // initialize the LED pin as an output:
      for (int thisPin = 0; thisPin < 15; thisPin++) {
        pinMode(list[thisPin], OUTPUT);
      }

    }

    void loop() {
      // read the state of the pushbutton value:
      int output = analogRead(pot_pin);
      int led_value = map(output, 0, 1023, 0, 255);

      if (digitalRead(s1) == HIGH) {
        for (int thisPin = 0; thisPin < 15; thisPin++) {
          if (digitalRead(s2) == LOW) {
            // turn the pin on:
            analogWrite(list[thisPin], led_value);
            //digitalWrite(thisPin, HIGH);
            delay(timer);
          }
          else {

            for (int de = 14; thisPin < 15; thisPin++) {
              analogWrite(list[thisPin], led_value);
              analogWrite(list[de], led_value);
              //digitalWrite(thisPin, HIGH);
              //digitalWrite(de, HIGH);
              delay(timer);
              de--;
            }

          }
        }
        flag1 = true;

      }
      if (digitalRead(s2) == HIGH and flag1 == true) {
        for (int thisPin = 0; thisPin < 15; thisPin++) {
          if (digitalRead(s1) == LOW) {

            digitalWrite(list[thisPin], LOW);
            delay(timer);
          }
          else {
            for (int de = 14; thisPin < 15; thisPin++) {
              digitalWrite(list[thisPin], LOW);
              digitalWrite(list[de], LOW);
              delay(timer);
              de--;
            }

          }

        }
        flag1 = false;
      }
    }

  [1]: https://i.stack.imgur.com/AAy2T.png
  [2]: https://youtu.be/ZQg_xbGQNE0

title: Code not working

Answers: 0


body:
I hope someone can help me.

I'm using a Mega with RC522, and this happens:

I use a tag, it reads the right serial (e.g. AA:BB:CC:DD). Then I use a second tag and sometimes it gives me the correct value (e.g. 00:11:22:33), but often it gives me the previous tag serial (AA:BB:CC:DD). After a few attempts, it finally gives me the right one (00:11:22:33).

I really can't find what's wrong and i'd be grateful if someone could shed some light.

Here's the code:

    if (RC522.PICC_IsNewCardPresent())  {
               RC522.PICC_ReadCardSerial();
              String strID = "";
            for (byte i = 0; i < 4; i++) {
              strID +=
                (RC522.uid.uidByte[i] < 0x10 ? "0" : "") +
                String(RC522.uid.uidByte[i], HEX) +
                (i != 3 ? ":" : "");
            }
            String seriale = strID;

            if (seriale != "0"){

              for(h=0; h<=numerogiocatori -1;h++){

                if (seriale == seriali[h]) {
                  lcd.clear();
                  lcd.print("Saldo Gioc. ") ;
                  lcd.print(h + 1) ;
                  Serial.print("tag ID: ");
                  Serial.print(seriale);
                  Serial.print(" .    ");
                  lcd.setCursor(0, 1);
                  lcd.print(totaledenaro[h]) ;
                  delay(1500);
                  lcd.clear();
                  lcd.print("Importo");
                  lcd.setCursor(0, 1);
                }
              }
            }}}

Thanks to anyone willing to help!

title: RFID RC522 reads the previous tag serial with different tag

Answers: 1

body:
One rule for writing safety code is :

*The return value of non-void functions must be checked by each calling function, and the validity of parameters must be checked inside each function.*

You forgot to check if the tag has been readed i.e the return value of PICC_ReadCardSerial. If it fails the value is not updated, that is the reason why the value is still the old one.

Using the following code (from the ReadNUID example of the MFRC522 library https://github.com/miguelbalboa/rfid/blob/master/examples/ReadNUID/ReadNUID.ino)

    // Init array that will store new NUID
    byte nuidPICC[4];

    void loop() {

      // Look for new cards
      if ( ! rfid.PICC_IsNewCardPresent())
        return;

      // Verify if the NUID has been readed
      if ( ! rfid.PICC_ReadCardSerial())
        Serial.println(F("NUID has NOT been readed."));

      if (rfid.uid.uidByte[0] != nuidPICC[0] ||
        rfid.uid.uidByte[1] != nuidPICC[1] ||
        rfid.uid.uidByte[2] != nuidPICC[2] ||
        rfid.uid.uidByte[3] != nuidPICC[3] ) {
        Serial.println(F("A new card has been detected."));

        // Store NUID into nuidPICC array
        for (byte i = 0; i < 4; i++) {
          nuidPICC[i] = rfid.uid.uidByte[i];
        }

        Serial.println(F("The NUID tag is:"));
        printHex(rfid.uid.uidByte, rfid.uid.size);
        Serial.println();
      }
      else Serial.println(F("Card read previously."));

      // Halt PICC
      rfid.PICC_HaltA();

      // Stop encryption on PCD
      rfid.PCD_StopCrypto1();
    }

    void printHex(byte *buffer, byte bufferSize) {
          for (byte i = 0; i < bufferSize; i++) {
            Serial.print(buffer[i] < 0x10 ? " 0" : " ");
            Serial.print(buffer[i], HEX);
      }
    }

the result is
>A new card has been detected.

>The NUID tag is:

> 97 C6 6E 09

>**NUID has NOT been readed.

>Card read previously.**

>A new card has been detected.

>The NUID tag is:

> CC 16 5D 83

>A new card has been detected.

>The NUID tag is:

> 97 C6 6E 09

>**NUID has NOT been readed.

>Card read previously.**

>A new card has been detected.

>The NUID tag is:

> CC 16 5D 83

Sometimes when the second tag is used the tag is not read and the uid remains the same.


body:
I have a VSI SPWM Inverter Project, but my supervisor ask me to upgrade it to a VFD Inverter. I've found a code about how to generate 3 phase SPWM in this [article][1], and i've tried the code. The output signal is great. But i need to improve the code to VFD code with range frequency 0-100 Hz. I've found a reference about VFD from this [one][2] and tried to modify the SPWM code, but failed. Could anyone help me to improve the code, please? Here is the SPWM code..

    int i=0;
    int j=0;
    int k=0;
    int x=0;
    int y=0;
    int z=0;
    int OK=0;
    int OK1=0;
    int OK2=0;
    int OK3=0;
    int OK4=0;
    int sinPWM[]={1,2,5,7,10,12,15,17,19,22,24,27,30,32,34,37,39,42,
    44,47,49,52,54,57,59,61,64,66,69,71,73,76,78,80,83,85,88,90,92,94,97,99,
    101,103,106,108,110,113,115,117,119,121,124,126,128,130,132,134,136,138,140,142,144,146,
    148,150,152,154,156,158,160,162,164,166,168,169,171,173,175,177,178,180,182,184,185,187,188,190,192,193,
    195,196,198,199,201,202,204,205,207,208,209,211,212,213,215,216,217,219,220,221,222,223,224,225,226,227,
    228,229,230,231,232,233,234,235,236,237,237,238,239,240,240,241,242,242,243,243,244,244,245,245,246,246,
    247,247,247,248,248,248,248,249,249,249,249,249,255,255,255,255,249,249,249,249,249,248,
    248,248,248,247,247,247,246,246,245,245,244,244,243,243,242,242,241,240,240,239,238,237,237,236,235,234,
    233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,217,216,215,213,212,211,209,208,207,205,204,
    202,201,199,198,196,195,193,192,190,188,187,185,184,182,180,178,177,175,173,171,169,168,166,164,162,160,
    158,156,154,152,150,148,146,144,142,140,138,136,134,132,130,128,126,124,121,119,117,115,113,110,108,106,
    103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,66,64,61,59,57,54,52,49,47,44,42,39,37,34,32,30,
    27,24,22,19,17,15,12,10,7,5,2,1};

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

    pinMode(4, OUTPUT);
    pinMode(13,OUTPUT);
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    pinMode(2,OUTPUT);
    pinMode(3,OUTPUT);
    pinMode(5,OUTPUT);

    cli();// stop interrupts
    TCCR0A=0;//reset the value
    TCCR0B=0;//reset the value
    TCNT0=0;//reset the value
    //0b allow me to write bits in binary
    TCCR0A=0b10100001;//phase correct pwm mode
    TCCR0B=0b00000001; //no prescaler

    TCCR2A=0;//reset the value
    TCCR2B=0;//reset the value
    TCNT2=0;//reset the value
    //0b allow me to write bits in binary
    TCCR2A=0b10100001;//phase correct pwm mode
    TCCR2B=0b00000001; //no prescaler

    TCCR3A=0;//reset the value
    TCCR3B=0;//reset the value
    TCNT3=0;//reset the value
    //0b allow me to write bits in binary
    TCCR3A=0b10100001;//phase correct pwm mode
    TCCR3B=0b00000001; //no prescaler
    TCCR1A=0;//reset the value
    TCCR1B=0;//reset the value
    TCNT1=0;//reset the value
    OCR1A=509;// compare match value
    TCCR1B=0b00001001; //WGM12 bit is 1 for CTC mode and no prescaler

    TIMSK1 |=(1 << OCIE1A);// enable interrupts

    sei();//stop interrupts
    }
    ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
    if(i>313 && OK==0){// final value from vector for pin 13
    i=0;// go to first value of vector
    OK=1;//enable pin 4
    }
    if(i>313 && OK==1){// final value from vector for pin 4
    i=0;//go to firs value of vector
    OK=0;//enable pin 13
    }
    x=sinPWM[i];// x take the value from vector corresponding to position i(i is zero indexed)
    i=i+1;// go to the next position
    if(OK==0){
    OCR0B=0;//make pin 4 0
    OCR0A=x;//enable pin 13 to corresponding duty cycle
    }
    if(OK==1){
    OCR0A=0;//make pin 13 0
    OCR0B=x;//enable pin 4 to corresponding duty cycle
    }

    if ((i==209) || OK1==1){//if i equal with 209 enable second signal
    OK1=1;//mantain if function
    if(j>313 && OK2==0){// final value from vector for pin 10
    j=0;// go to first value of vector
    OK2=1;//enable pin 9
    }
    if(j>313 && OK2==1){// final value from vector for pin 9
    j=0;//go to firs value of vector
    OK2=0;//enable pin 10
    }
    y=sinPWM[j];// y take the value from vector corresponding to position j(j is zero indexed)
    j=j+1;// go to the next position
    if(OK2==0){
    OCR2B=0;//make pin 9 0
    OCR2A=y;//enable pin 10 to corresponding duty cycle
    }
    if(OK2==1){
    OCR2A=0;//make pin 10 0
    OCR2B=y;//enable pin 9 to corresponding duty cycle
    }
    }
    if ((j==209) || OK3==1){//if j equal with 209 enable third signal
    OK3=1;//mantain if function
    if(k>313 && OK4==0){// final value from vector for pin 5
    k=0;// go to first value of vector
    OK4=1;//enable pin 2
    }
    if(k>313 && OK4==1){// final value from vector for pin 2
    k=0;//go to firs value of vector
    OK4=0;//enable pin 5
    }
    z=sinPWM[k];// z take the value from vector corresponding to position k(k is zero indexed)
    k=k+1;// go to the next position
    if(OK4==0){
    OCR3B=0;//make pin 2 0
    OCR3A=z;//enable pin 5 to corresponding duty cycle
    }
    if(OK4==1){
    OCR3A=0;//make pin 5 0
    OCR3B=z;//enable pin 2 to corresponding duty cycle
    }
    }
    }
    void loop() {

    }

  [1]: http://www.eprojectszone.com/how-to-generate-three-phase-spwm-signal-with-arduino/
  [2]: https://github.com/carneeki/OpenVFD/blob/master/software/OpenVFD.ino

title: How to make Variable Frequency Drive (VFD) Inverter using Arduino

Answers: 0


body:
I'm trying to make the led switch on/off by the same case(): code.
But its not working could anyone help me?

title: How do I turn on/off led with the same IR button?

Answers: 1

body:
It would be good if you add your sketch if you have one.

In principle, you have to create a boolean variable which keeps the current state of the LED. When you get an IR command, inside the IR button handler invert the state of the boolean. Than change the LED accordingly.

Something like:

Const/Global variable:

    #define LED_PIN 8

    int ledState;

In setup:

     ledState = FALSE;
     digitalWrite(LED_PIN, ledState);

In side loop:

    case IR_BUTTON_CHANGE_LED:
       ledState = ledState == LOW ? HIGH : LOW; // Invert state
       digitalWrite(LED_PIN, ledState); // Set LED according to state
       break;


body:
The following is the code that I am trying but the problem is steppers rotate one after each other. However, I want to rotate steppers simultaneously.
This code for two stepper motors.

    int pulse=3;

    int direc=4;

    int pulse1=5;

    int direc1=6;

    int i,j,k;

    float angle[5][3]={{360,360,3},{7,8,9},{11,12,13},{14,15,16},{17,18,19}};

    float steps;

    void motor1(){

      for(k = 0; k<=4; k++){

        Serial.println(angle[k][0]);

        steps = (1600*angle[k][0])/360;

        Serial.println(steps);

        for(j = 0; j<=steps;j++){

          digitalWrite(3,HIGH);

          delayMicroseconds(100);

          digitalWrite(3,LOW);

          delayMicroseconds(100);
            }

    }

    }

    void motor2(){

      for(k = 0; k<=4; k++){

        Serial.println(angle[k][1]);

        steps = (1600*angle[k][1])/360;

        Serial.println(steps);

        for(j = 0; j<=steps;j++){

          digitalWrite(5,HIGH);

          delayMicroseconds(100);

          digitalWrite(5,LOW);

          delayMicroseconds(100);

            }

    }

    }

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

      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
    }

    void loop(){
        motor1();

        motor2();

       //while(1);
    }

title: How to rotate two or more steppers simultaneously by giving ARRAY of angles?

Answers: 2

body:
I can't understand clearly what you want, but maybe you want to drive your two servos simultaneously. To do this, after you determine the angle of servos, you can drive them without delay between their commands.

Like you use above, you can't drive them at the same time, there are loops and they have to be completed before the next instruction is run so your servos wait each other.

Here is a good example code for you:

    #include <Servo.h>

    Servo myservo1;  // create servo object to control a servo
    Servo myservo2;  // create servo object to control a servo

    float angle[5][3]={{360,360,3},{7,8,9},{11,12,13},{14,15,16},{17,18,19}};

    void setup() {
      myservo1.attach(9);  // attaches the servo on pin 9 to the servo object
      myservo2.attach(10);  // attaches the servo on pin 10 to the servo object
    }

    void loop() {
      for(k = 0; k<=4; k++){
        pos = (1600*angle[k][0])/360; //Calculate the angle which you want

        //The most impportant part, there shouldn't be a delay between them
        myservo1.write(pos);              // tell servo to go to position in variable 'pos'
        myservo2.write(pos);              // tell servo to go to position in variable 'pos'

        delay(1000);                       // waits 1000ms for the servo to reach the position
      }
    }

body:
(Half a year ago, but what the hey...)

Your motor1() and motor2() are currently written as:

    do until done:
      take a step
      wait
    end

, so yeah, one finishes before the next one even starts.

Each motor function needs to do:

    if motor's current-position is not the final position,
       if it is time to take a step,
          take a step
          calc when to take another step
          calc motor's new current-position
       end
    end

Now call your motor functions *as frequently as possible*. Notice that either `if` test can cause the function to return without doing anything - that is *intentional*.

This is non-blocking programming - coding in such a way that *nothing keeps control while waiting for something to happen* (clock ticks, in this case), it just does something, or does nothing, *right now*, if there is or is not something to do right now, but it *does release the processor* (the function returns immediately) whether it did something or not.

I call these functions "maybe-do" functions:

 - maybe step a motor (if, and only if, a certain interval has passed, step the motor);

 - maybe light an LED (if, and only if, the button is being pressed and it wasn't pressed the last time we looked, turn on the LED;

 - maybe read the terminal keyboard (if there is at least one character in the Serial input buffer, collect a character).

Then your loop() function should do *nothing but* call each maybe-do function, in sequence, as *fast as possible*. And it follows from the above that your maybe-do functions need to execute as quickly as possible and do no more than is necessary to (1) decide whether to act, and if so, (2) to carry out its action, and (3) in either case, return immediately.

<br>
And - Bang-Boom! - right there is a half-semester course in block-free programming without interrupts!


body:
I'm working on a vending machine project and I'm using CH-926 and an Arduino Uno for that. I've already set the coin accepter for different number of coins and respective output pulses. I'm unable to get the desired output for this. With every coin I insert the output varies even when I put the same coin.

    int pulse = 0;

    void coin_value() {
      pulse = pulse + 1;
    }

    void setup() {
      Serial.begin(9600);
      pinMode(2, INPUT);
      Serial.println("Ready to be collected");
    }

    void loop() {
      if (digitalRead(2) == HIGH) {
        attachInterrupt(0, coin_value, FALLING);

        if (pulse == 3) {
          Serial.println("50");
        }
        if (pulse == 2) {
          Serial.println("20");
        }
        if (pulse == 1) {
          Serial.println("10");
        }
      }

      pulse = 0;
    }

For each coin there are different specific pulses which helps to recognize the coin.`int pulse=0;`.

So when I insert coin 1 then the output should be 10, for coin 2 the output should be 20 and for coin 3 the output should be 50.

title: Coin recognition using Coin Accepter in Arduino Uno

Answers: 2

body:
Your code is faulty in a number of respects.

---

1. `pulse` should be declared volatile, i.e.

        volatile int pulse = 0;

    That is because it can change in an interrupt service routine.

---

2. You should only do `attachInterrupt` once, in `setup`.

---

3. Your code to display the count will be timing dependent. What if you happen to display the count after one pulse has arrived, but before they all have? Then you set the count back to zero.

---

Better would be something like this, untested however:

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

    volatile int pulse = 0;

    void coin_value() {
      pulse = pulse + 1;
    }

    void setup() {
      Serial.begin(9600);
      pinMode(2, INPUT);
      Serial.println("Ready to be collected");
      attachInterrupt(0, coin_value, FALLING);
    }

    void loop() {

      if (pulse > 0)
        {
        delay (1000);   // let the other pulses arrive
        if (pulse == 3) {
          Serial.println("50");
        }
        if (pulse == 2) {
          Serial.println("20");
        }
        if (pulse == 1) {
          Serial.println("10");
        }
        pulse = 0;  // clear for next time
      }

    }

---

(Edited to add)

Even then your test for 1/2/3 might fail if the coin acceptor sends the pulses twice. Then you might get 2/4/6 pulses. You probably need to display something if there is another count, eg.

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

      if (pulse == 3) {
        Serial.println("50");
      }
      else if (pulse == 2) {
        Serial.println("20");
      }
      else if (pulse == 1) {
        Serial.println("10");
      }
      else {
         Serial.print ("Unexpected number of pulses: ");
         Serial.println (pulse);
      }

body:
First of all you said

> So when I insert coin 1 then the output should be 10, for coin 2 the
> output should be 20 and for coin 3 the output should be 50.

Yes coin 3 would be 50 but it does not means that coin 3 has 3 impulses(he will have 5 impulse), I recommend to you always use this formula:

> Coin_Value = Pulse_Count * Denomination.

I don't recommend to you use 3 Impulses from coin acceptor Because you don't have 15 cent and 30 cent coins. In most cases Coin acceptors have:

> 1/4 1/2 1 2 4 5 8 10 impulses

Generally I prefer to save all data in variables

So lets get to variables for code

    const int coinIntPin = 2;          //interruptPin 0 is digital pin 2
    volatile boolean newCoin = false;
    volatile int pulseCount;          //counts pulse for
    volatile int timeOut = 0;         //counts timeout after last coin inserted
    float coinType;
    float denomination = 0.50;         // in my case 1 Pulse = 0.50 $
    int max_impulse = 4;              // this is the maximum impulses I use
    volatile long timeFPulse = 0;     // to determine when First impulse was interrupted
    volatile long interval;           // to determine interval from first and last impulse

And always use attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); [It is recommended by Arduino][1]  as below:

  [1]: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

    void setup(){
        Serial.begin(9600);
        attachInterrupt(digitalPinToInterrupt(coinIntPin), coinInserted, FALLING);

    }

And I will give you rest of code:

    void coinInserted(){
        newCoin = true;
        timeFPulse = millis();
        pulseCount++;
    }

    void loop()
    {

         while (newCoin == true)
        {
                interval = millis() - timeFPulse;  //interval from first and last impulse
                if(pulseCount == max_impulse || (interval > 500 && pulseCount > 0)) //Max_impulse will avoid any extra impulses for any reason.
                {
    // This is the reason why I recommended to you use 1 2 4 5 10 20 Impulses instead of 3 7 9 etc...
                  coinType = pulseCount * denomination;
                  newCoin = false;
                  sendData();
                  delay(5);

                 }

        }
    }

    void sendData(){
      Serial.print("Do what ever you want. Inserted Money = ");
      Serial.println(coinType);
      coinType = 0;  // remove if you want to save Coins and print sum of inserted coins
      pulseCount = 0;  // remove if you want to save impulses determined by coin acceptor
    }

And Finally look at ( interval > 500 ) If you have different max impulses you must change 500 to (impulse length * Max impulses + 100); so if you have max 10 impulses you must enter 1100 and not 500 (in my case);


body:
This is my first Arduino project, and I would like to stop my servo's loop after 1 minute. Can someone help me?

    #include <Servo.h>
    Servo myservo;

    void setup()
    {
      myservo.attach(5);
    }

    void loop()
    {
      myservo.write(45);
      delay(1000);
      myservo.write(125);
      delay(1000);
    }

Thanks!

title: How can i stop a loop after 1 minute?

Answers: 3

body:
To answer your question as asked, add this to `loop()`:

    if (millis() >= 60000) exit(0);

However, I would suggest you seriously consider Jot's comment: simply
stopping `loop()` from running is most of the time _not_ what you may
want to do.

body:
As suggested by Jot in a comment, one way would be to simply do what you want (which takes roughly two seconds per iteration) in a loop, like this:

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

    #include <Servo.h>
    Servo myservo;

    void setup()
    {
      myservo.attach(5);

      for (int i = 0; i < 30; i++)
        {
        myservo.write(45);
        delay(1000);
        myservo.write(125);
        delay(1000);
        }
    }

    void loop()
    {
    }

---

The problem with that is it relies upon knowing how long your delays are, and assumes that the `myservo.write()` functions take no time. A better method is:

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

    #include <Servo.h>
    Servo myservo;

    void setup()
    {
      myservo.attach(5);

      unsigned long start = millis ();

      while (millis () - start <= 60000)  // for 60 seconds
        {
        myservo.write(45);
        delay(1000);
        myservo.write(125);
        delay(1000);
        }
    }

    void loop()
    {
    }

This uses the `millis()` function call to find out how much time has elapsed, and wait for 60000 milliseconds (60 seconds).

---

I've put the code into `setup` because that is where you put things you want done once.

body:
Another way to handle this is to use a variable endTime to tell the loop when to stop moving the servo:

    unsigned long endTime;

    void setup()
    {
      myservo.attach(5);
      endTime = millis() + 60000;
    }

    void loop()
    {
      if (millis() <= endTime) {
        myservo.write(45);
        delay(1000);
        myservo.write(125);
        delay(1000);
      } else {
        //code to run once the servo is done running
      }
    }

This code will move the servo back and forth for about 1 minute, then stop. It's set up so you can do something else once the loop has completed.

Note that by using a variable endTime and leaving your servo code in the loop() function, you can have your program start doing something else once the motor motion is completed. You can also add code to set up a new value in EndTime, at which point the servo will start moving back and forth again.

Also note that using delay is bad practice. When you do that you bring the arduino to a full stop while the delay code is running. You can't be doing something else. Say, for example, you wanted to move 2 different servos at different time intervals.

Instead of using delays you should track the end time for each phase of your loop, and execute your code once that end time passes.


body:
I'm relatively new to microcontroller programming, so please excuse me if my question is dumb. I've created a simple device that allows me to control 4 relays based on temperature. I bought four DS18B20 sensors, 4 relay board and Wemos D1. Everything works fine - I'm able to read the temperature of each sensor based on their address.

But I started wondering how I can replace a single DS18B20 without recompiling the code; currently this isn't possible. After searching a bit I found a couple of questions about the order of 1Wire sensors. For example, [this one.][1] I have no control over the order in which sensors are detected.

Is there a best practice when it comes to configuring DS18B20 sensors?
I would like to set up my device. By set up, I mean that I would like to assign a specific DS18B20 to a specific relay.

I imagine it like so:

 1. Take a new DS18B20, connect it to a device and power the device.
 2. The device should scan for DS18B20 sensors. If it finds one then it should assign it to relay 1 and store its address in EEPROM.
 3. Then unplug the device from power, plug the second DS18B20 and power the device again.
 4. The device again scans for DS18B20 sensors. It finds 2 devices. The first one is known (the address was stored in EEPROM) so it is skipped. The second is assigned to relay 2 and the address is stored in EEPROM.
 5. The same procedure is applied to the third and fourth sensors.
 6. If four sensors are connected (the addresses are from EEPROM), then the device can run.
 7. When the user wants to replace a non-functioning sensor, the same procedure can be used.

As I wrote, I'm new to microcontroller programming, so if there is a better way please let me know. I'm mostly learning by following examples and tutorials, so if anyone knows of an example showing such a configuration procedure I'll be grateful for any materials.

  [1]: https://arduino.stackexchange.com/questions/34104/ds18b20-order-of-sensors-on-a-cable

title: Detect DS18B20 sensors and correctly assign them to relays

Answers: 1

body:
If you can easily disconnect the sensors one at a time then your way is fine.

If you can't easily disconnect them then you can maybe use readings to set the order, although this depends on the environment. If, for example, all the sensors are generally room temperature then you have the code check the temp of all the sensors at start up. If it finds one sensor at less than 0C then assign that sensor to the least-recently-replaced relay index (also stored in EEPROM).

Then when you want to put a sensor into the working set, hold an ice cube on it for a few seconds before powering up the controller. There are other combinations of this technique you can imagine that use a button or jumper wires to specifically set the index of the out-of-range-at-startup sensor.

Alternately if you have an extra pin on the Arduino, then you can make a procedure where you connect a new sensor to that pin before attaching it to the string. You can make a rule like "if you ever see a sensor on pin X then remember its device ID and assign it to relay Y". There are lots of UI ways to pick Y. Note that [you do not even need any extra hardware for this][1].

  [1]: https://wp.josh.com/2014/06/23/no-external-pull-up-needed-for-ds18b20-temp-sensor/


body:
I'm building a rig with multiple DSLR cameras.  I need to synchronize the cameras to take a photos with lowest possible latency.  The only constraint is we want the ability to address each camera individually if needed.

I've seen in other posts:
https://arduino.stackexchange.com/questions/13233/choosing-wireless-tech-for-lowest-possible-lag

NRF24L01+ seems to be a good choice.  An answer on that post states:
sending a 32 byte payload...283µs on 2Mbps mode.

Given the  esp8266 has a clock speed of 80MHz/160MHz I'm not too concerned about the lag involved in processing the signals.

Most multi-cast information out there is for sensor arrays, so multiple out single in.  I'm after resources on single out multiple in for NRF24L01+ networks.

Added bonus of esp8266 is that non timing critical tasks such as logging and error checking could be performed over wifi so NRF24L01+ would be purely for one -way triggering.

If each camera had it's own esp8266 based board with attached NRF24L01+ hardware and was given an address in software from 0-255, is it possible to broadcast a single 32 byte packet of data where each bit would represent a camera address and have all receiver devices receive the same signal, do an AND against it's address and trigger if needed?

title: Lowest latency triggering multiple Arduinos using NRF24L01+

Answers: 1

body:
Yes, that should work, however also think about the following issues:

- What if one (or more) camera does not receive the signal? You might need to add an ACK signal, but of course this will reduce the latency (a lot). If you don't want an ACK signal
- To prevent an ACK, you can send the signal many times (and cameras who already processed the signal not react for a fixed amount of time). Of course it will received by the other cameras (at least) 283 us later.
- If reliability is important, you could try using a less high speed, the latency will go up, but reality too.

Also you probably can fire the cameras even faster, if you first send the address bytes (4 bytes). And than send the shoot signal which can be in principle 1 bit. You can use one of the bits for that in case 128 cameras would suffice. Or send one byte extra which contains the signal to shoot.


body:
I'm building a USB keyboard that has two buttons - space and enter. The plan is to use this USB keyboard (with an Apple Lightning connector to USB) with the built in iOS switch control. I bought the lightning to USB dongle, and hooked it up to a normal keyboard, and it works fine.

Next, I took an Arduino Micro (ATMEGA32u4) and programed it to act as a keyboard with the two keys I need (space and enter). On a PC, it works just fine, but when I hook it up to my iPhone, I get the message:

    Arduino Micro: The connected device requires too much power.
I've done quite a bit of research on this, and I found [this][1] post. In a nutshell, that post said that when you connect a device to an iOS device, one of the first things it does is tell the iDevice how much current it *could potentially* draw. This number (about 200mA for the Arduino Micro) is what decides whether the iDevice will support the device or not, when in truth, the device will not come close to its max current draw, at least not in my case.

I hooked up a meter to the normal keyboard, and it draws just over 4mA. When I hook up the Arduino, it is drawing almost 40mA. While the Arduino is drawing much more than the keyboard, it should be okay, because when I plugged in a flash drive, it was drawing 50mA, but the iPhone didn't complain.

There is my story, here is my question:

Is there any way to change it so that the Arduino Micro doesn't request so much power? In other words, is there a way to reset the value that is causing the iPhone to not use the device?

----------

  [1]: https://arduino.stackexchange.com/questions/37343/high-power-consumption-of-atmega32u4-when-connected-to-ios-device

title: Arduino Micro draws too much power from iPhone. How can I change that?

Answers: 2

body:
Yes, but it requires manual modification of the Arduino core software.

1. Find the file `USBCore.h` within your AVR boards installation (it could be in the data storage folder wherever that is on your OS, or within the actual IDE software)
2. Look for the line `#define D_CONFIG(_totalLength,_interfaces) \`
3. The *next* line has the power setting.  Change `USB_CONFIG_POWER_MA(500)` to what you require (for example `USB_CONFIG_POWER_MA(50)`

body:
The power consumption is part of the exchange with the PC when it is plugged in. You can change that. Find the file `USBCore.h` in your Arduino install directory. In my case (under Linux) it was:

    ./hardware/arduino/avr/cores/arduino/USBCore.h

Inside that file, at around line 269 (depending on the distribution) you should see these lines:

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

    #define D_CONFIG(_totalLength,_interfaces) \
     { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) }

On the right of the second line is the requested power consumption in milliamps (currently 500). Change that to (say) 100:

That is, change `USB_CONFIG_POWER_MA(500)` to `USB_CONFIG_POWER_MA(100)`.

Save and recompile.

You may find that the bootloader initially requests 500 mA even with this change (as it initially runs the bootloader). However when the sketch starts it should re-establish a USB connection and only request 100 mA. To fix that you would need to recompile the bootloader with the same fix, and reinstall it, a somewhat more complex task.

Another possible approach would be to tweak the fuses so that it doesn't run the bootloader, if you have finished debugging your code. Only do that if you are confident with playing with the fuses.


body:
I am working on a project where I need to split incoming data from serial (time to be exact, so aa:bb:cc) and need to split it into aa then bb and cc, ideally into  an array. I know I could use readStringUntil and make 3 separate variables, but I would prefer it is in arrays. Here is the code that supposed to do this. It works with predefined string (eg. 00:00:00), but with reading serial it says that the initializer fails to determine size of "input".
Thank you in advance for helpful suggestions.

Here is the code:

    void setup() {
     FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
      Serial.begin(9600);
      while(!Serial.available()){} //wait until Serial data received
      String vst = Serial.readString();
      char buf[vst.length()+1];
      vst.toCharArray(buf, vst.length());
      char input[] = vst;
      char delic[] = ":";
      char* sub = strtok(input, delic);
      while(sub != NULL){
       Serial.println(ptr);
        sub = strtok(NULL, delic);
      }
}

title: Splitting a Serial.readString into string array

Answers: 1

body:
Your main problem is this:

    char buf[vst.length()+1];

You can't initialize an array with the return value of a function.

Instead you would need to use `alloca` to perform the same function:

    char *buf = alloca(vst.length()+1);

However, the way you're doing it is wasteful. You don't need `buf` at all.  You can directly access and manipulate the internal `char` buffer inside the string using `vst.c_str();`.

For convenience you can point `buf` at it:

    char *buf = vst.c_str();

To complete the picture here's a routine that takes the string and gives you three integers. Since we expect a specific format with only 3 sections to it we don't really need a loop.

    // Use readStringUntil to avoid the 1 second delay.
    String vst = Serial.readStringUntil('\n');
    char *buf = vst.c_str();

    char *hourString = strtok(buf, ":");
    char *minuteString = strtok(NULL, ":");
    char *secondString = strtok(NULL, ":");

    if (secondString != NULL) { // Will only be true if we have two colons
        int hours = atoi(hourString);
        int minutes = atoi(minuteString);
        int seconds = atoi(secondString);

        Serial.print("It is ");
        Serial.print(minutes);
        Serial.print(" and ");
        Serial.print(seconds);
        Serial.print(" seconds past ");
        Serial.println(hours);
    } else {
        Serial.println("Invalid time format");
    }


body:
I've been dealing with this for quite a while now and searching all over for answers.. I'm trying to put together two floats into a char*. Separated by a ",".
This is the code I'm working with.
<!-- language-all: lang-cpp -->

    #include <DHT.h>
    #include <RH_ASK.h>
    #include <SPI.h>

    #define DHT_pin 10
    #define DHT_type DHT11

    DHT dht(DHT_pin, DHT_type);
    RH_ASK rf_driver;

    float temp;
    float hum;

    char ch_temp[6];
    char ch_hum[6];
    char msg_out[12] = "";

    void setup() {
      Serial.begin (115200);
      dht.begin();
      if (rf_driver.init()) {
        Serial.println("Radio transmitter initiated..");
      }
      else {
        Serial.println("Radio transmitter failed to initiate..");
        delay(1000);
      }
    }
    void loop() {
      temp = dht.readTemperature();
      hum = dht.readHumidity();

      dtostrf(temp, 5, 2, ch_temp);
      dtostrf(hum, 5, 2, ch_hum);
      strcat(msg_out, ch_temp);
      strcat(msg_out, ",");
      strcat(msg_out, ch_hum);

      Serial.println(msg_out);
      rf_driver.send((uint8_t *)msg_out, strlen(msg_out));
      rf_driver.waitPacketSent();
      Serial.print("data sent, package size: ");
      Serial.println(strlen(msg_out));
      delay(1000);

    }

I have tried using different sizes of the char arrays, but it just goes crazy.
This is the console output:

    Radio transmitter initiated..
    22.00,34.00
    data sent, package size: 11
    ⸮⸮Radio transmitter initiated..
    22.00,34.00
    data sent, package size: 11

So on its way through the second loop it fails, restarts and then on its third way through it just gives up... What am I doing wrong? :( Really sad over this.

title: Memory problem? dtostr() and strcat()

Answers: 3

body:
If you remove the RF and sensor code, the sketch seems to work correctly when printing to the serial monitor. The first time you call `rf_driver.send()` in the loop, it works. The second time through the loop, and every time there after, it starts printing corrupted data. I don't have a definitive answer why this is happening, but I do have a way to "fix" it (or a "hack", if you prefer to call it that).

Using `memset()` to set the `msg_out` char array to all 0's **before** you use it seems to fix the problem. Here is a test sketch which is very similar to yours. I'm using some hard coded values for the sensor data because I don't have one of those sensors.

    #include <RH_ASK.h>
    #include <SPI.h>
    RH_ASK rf_driver;

    float temp;
    float hum;

    char ch_temp[6];
    char ch_hum[6];
    char msg_out[12] = "";

    void setup() {
      Serial.begin (9600);
      if (rf_driver.init()) {
        Serial.println("Radio transmitter initiated..");
      }
      else {
        Serial.println("Radio transmitter failed to initiate..");
        delay(1000);
      }
    }
    void loop() {

      // Set the buffer contents to all 0's
      memset(msg_out, 0, sizeof(msg_out));

      temp = 12.345;
      hum = 67.890;

      dtostrf(temp, 5, 2, ch_temp);
      dtostrf(hum, 5, 2, ch_hum);
      strcat(msg_out, ch_temp);
      strcat(msg_out, ",");
      strcat(msg_out, ch_hum);

      Serial.println(msg_out);
      rf_driver.send((uint8_t *)msg_out, strlen(msg_out));
      rf_driver.waitPacketSent();
      Serial.print("data sent, package size: ");
      Serial.println(strlen(msg_out));
      delay(1000);
    }

body:
Your sketch is running on borrowed memory.
Every time the loop function runs, the new text is concatenated with `strcat()` and the buffer `msg_out` is never reset.
The first time 12 bytes are used, the second time 23 bytes, the third time 34, and so on.

The solution in the answer by @VE7JRO will fix that, but I prefer not to use `dtostrf()` and transmit binary data.

I see a few other problems as well:

 - Why do you want to transmit readable ASCII text? Use binary data.
   Either float numbers or integers. For example an integer in 1/100 degrees.
 - The RadioHead library uses a lot of memory. You can not use an other
   library that uses also a lot of memory.
 - The value of '5' for dtostrf is the **minimal** width,
   so you better make those arrays for example 20 bytes.
   I prefer to put those arrays temporarily on the stack.
 - The DHT11 is not accurate. If you upgrade to a better sensor with I2C,
   then you need more libraries (the Wire library and a sensor library),
   and you might run out of sram memory.
 - When using the RadioHead library in default mode, it uses three
   pins (rxPin=11, txPin=12, pttPin=10). You better add a comment
   section to your sketch to explain that you should not use those pins.
   You have already a
   conflict at pin 10 for the DHT sensor and the pttPin.

----------

The old and no longer supported VirtualWire library has some bugs, but it uses less memory than the RadioHead library. The RadioHead library is not optimized for Arduino boards like the Uno, Nano, Leonardo, and others. It even requires to `#include <SPI.h>` because that is often used with transceivers, even if the SPI bus is not used in RH_ASK mode (thanks to @VE7JRO for explaining this in the comment below).

----------

**The easiest way** to transmit more than one value is with an array.

    float myData[2];
    myData[0] = 23.456;
    myData[1] = 68.0;
    rf_driver.send((uint8_t *)myData, sizeof(myData));

The `sizeof()` is not a real function, it tells the compiler to fill in the size of that variable. Since a `float` is 4 bytes, you may also fill in the number 8 for the second parameter.

There are a number of solutions for the receiver. I like to use a pointer to the buffer, but perhaps it is easier to copy them to variables with `memcpy()`.

    float myData[2];
    if (driver.recv(buf, &buflen)) {
      if (buflen == sizeof(myData) {  // extra check
        memcpy((uint_8 *)myData, buf, sizeof(myData));
        Serial.println(myData[0]);
        Serial.println(myData[1]);
      }
    }

When the receiver is also an Arduino board, then there should be no problem. When the receiver is something else, you might have to check if the [byte-order][1] is the same. The `float` variable of a Arduino is 100% IEEE compatible, but sometimes it is easier to use only integers.

**The most common way** is to use a `struct`. A `struct` is a package that can hold all sorts of data (integers, bytes, arrays, and so on). The receiver and the sender should have exactly the same definition for the `struct` of course.

  [1]: https://en.wikipedia.org/wiki/Endianness

body:
I'm late to the party, but here goes:

`msg_out[]` is a global but it doesn't need to be. Move it's definition and initialization into loop(), the only function that uses it. Then it gets initialized at every entry to loop() rather than just once at program initialization. There's no need to clear the array; just zeroing the zero-th element of it initializes it for character-string use, and that is what your initializer now does (but only once).


body:
I am trying to control a stepper motor wirelessly with a button. I am using the 433MHZ rf module and the Virtualwire library.

the code is working, the receiver is getting the messages from the transmitter, but the problem is the messages are sent extremely slowly, so much so that the receiver circuit led is flashing on and off instead of staying in the on position when the transmitter button is being held down. consequently the stepper motor stutters instead of moving smoothly.

I have tried increasing the bits per second in the vw_setup but that just makes the led flash faster and not stay in the on position. it also makes the stepper vibrate more.

how do i make the stepper motor move smoothly wirelessly over rf?

transmitter code:

    #include <VirtualWire.h>

    int currentlocation = 0;
    const int stepPin = 3;
    const int dirPin = 4;
    int active = 0;
    const int ledPin =  13;      // the number of the LED pin
    String dataout;
    char buffer[1];
    int idx=0;

    class Button {

      public:

        int pin;
        int state;
        int location;
        int Speed;
        int Direction;
        int active;
        int prevstate;

        Button(int pin1, int state1, int location1, int active1, int previousState)
        {
          pin = pin1;
          state = state1;
          location = location1;
          active = active1;
          prevstate = previousState;
        }

        Button(int pin1, int state1, int speed1, int direction1)
        {
          pin = pin1;
          state = state1;
          Speed = speed1;
          Direction = direction1;
        }

        Show(){
          if (digitalRead(pin) == HIGH){
              digitalWrite(ledPin, HIGH);
              } else {
              // turn LED off:
              digitalWrite(ledPin, LOW);
              }
        }
    };

    Button button(7,0,0,0,0);
    Button button2(8,0,30,0,0);
    Button Movebutton1(5,0,500,HIGH);
    Button Movebutton2(6,0,500,LOW);
    Button buttons[2] = {button, button2};
    Button Movebuttons[2] = {Movebutton1, Movebutton2};

    void setup() {
          vw_setup(2000);
          pinMode(stepPin,OUTPUT);
          pinMode(dirPin,OUTPUT);
          pinMode(ledPin, OUTPUT);
          Serial.begin(9600);      // open the serial port at 9600 bps:
    }

    void loop() {
        for (int i = 0; i<2; i++){
          buttons[i].Show();
          if (digitalRead(buttons[i].pin) == HIGH){
          sprintf(buffer, "%d", i);
          vw_send((uint8_t *)buffer, strlen(buffer));
          vw_wait_tx();
          }
        }
        for (int i = 0; i<2; i++){
          Movebuttons[i].Show();
          if (digitalRead(Movebuttons[i].pin) == HIGH){
          sprintf(buffer, "%d", i+2);
          vw_send((uint8_t *)buffer, strlen(buffer));
          vw_wait_tx();
          }
        }
    }

Receiver code:

    #include <VirtualWire.h>

    char message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages
    byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message
    int last_idx = 0;

    int currentlocation = 0;
    const int stepPin = 3;
    const int dirPin = 4;
    int active = 0;
    const int ledPin =  13;      // the number of the LED pin
    String str_out;

    class Button {

      public:

        int pin;
        int state;
        int location;
        int Speed;
        int Direction;
        int active;
        int prevstate;

        Button(int pin1, int state1, int location1, int active1, int previousState)
        {
          pin = pin1;
          state = state1;
          location = location1;
          active = active1;
          prevstate = previousState;
        }

        Button(int pin1, int state1, int speed1, int direction1)
        {
          pin = pin1;
          state = state1;
          Speed = speed1;
          Direction = direction1;
        }

        Relocate(){
          int shift = location - currentlocation;
          if (shift > 0){
            Direction = 0;
          }
          else{
            Direction = 1;
          }
          shift = abs(shift);
          digitalWrite(dirPin,Direction); // Enables the motor to move in a particular direction
          // Makes 200 pulses for making one full cycle rotation
          for(int x = 0; x < shift; x++) {
            digitalWrite(stepPin,HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPin,LOW);
            delayMicroseconds(500);
          }
          currentlocation = location;
        }

        Move(){
          digitalWrite(dirPin,Direction); // Enables the motor to move in a particular direction
          // Makes 200 pulses for making one full cycle rotation
            digitalWrite(stepPin,HIGH);
            delayMicroseconds(Speed);
            digitalWrite(stepPin,LOW);
            delayMicroseconds(Speed);
          if (Direction == 1){
          currentlocation -= 1;
          }
          else{
          currentlocation += 1;
          }
        }

        Show(){
          if (vw_get_message(message, &messageLength)){
              digitalWrite(ledPin, HIGH);
              } else {
              // turn LED off:
              digitalWrite(ledPin, LOW);
              }
        }
    };

    Button button(7,0,0,0,0);
    Button button2(8,0,30,0,0);
    Button Movebutton1(5,0,500,HIGH);
    Button Movebutton2(6,0,500,LOW);
    Button buttons[2] = {button, button2};
    Button Movebuttons[2] = {Movebutton1, Movebutton2};

    void setup() {
            // Initialize the IO and ISR
          vw_setup(2000); // Bits per sec
          vw_rx_start(); // Start the receiver
          Serial.begin(9600);
          pinMode(stepPin,OUTPUT);
          pinMode(dirPin,OUTPUT);
          pinMode(ledPin, OUTPUT);
    }

    void loop() {

          // Set buffer to size of expected message
        if (vw_get_message(message, &messageLength)){
        int idx=atoi(message);
        Serial.print(message);
        for (int i = 0; i<2; i++){
          buttons[i].Show();
          if (idx == i){
          buttons[i].Relocate();
          active = i;
          //buttons[i].location = currentlocation;
          }
        }
        for (int i = 2; i<4; i++){
          Movebuttons[i-2].Show();
          if (idx == i){
          Movebuttons[i-2].Move();
          buttons[active].location = currentlocation;
          }
        }
        }
    }

title: Stuttering motor using rf module

Answers: 1

body: What is the incoming message interval (1/incomingMessageFrequency)? Whenever the receiving end receives a "button-down" message, it should activate the motor for that interval + long enough to receive or not receive the next "button-down". Once the next "button-down" should have been received and has been missed, that's when you should stop the motor.