body:
I'm trying to solve some problems for a contest, and I have a problem with it. I have to implement a function that has 3 arguments like this:

    void foo(unsigned char* A, unsigned char* B, unsigned char* C);

And what comes in, is 6 bytes of data. I have to convert these 6 bytes of data to integer data (maybe long long). The problem is, I don't know how to map the bytes in the right order.

I'm using an Arduino Uno board.

Please help me with it.

title: How to map 6 bytes of raw data to long long type?

Answers: 3

body:
When passing data to functions you do this...

    foo(a,b,c);

You then extract the variables or data passed to the function like..

    void foo(unsigned char* A, unsigned char* B, unsigned char* C) {
        A = whatever;
        B = whatever;
        C = whatever;
    }

body:
The trick is to use a `union` data type and get full control of the mapping. The issue of data representation and endian is now under your control:

    uint64_t foo(uint8_t* A, uint8_t* B, uint8_t* C)
    {
      union {
        uint64_t X;
        struct {
          uint8_t A[2];
          uint8_t B[2];
          uint8_t C[2];
          uint8_t D[2];
        };
      } map;
    #if defined(MSB_ORDER)
      for (int i = 0, j = 1; i < 2; i++, j--) {
        map.A[i] = 0;
        map.B[i] = C[j];
        map.C[i] = B[j];
        map.D[i] = A[j];
      }
    #else
      for (int i = 0; i < 2; i++) {
        map.A[i] = A[i];
        map.B[i] = B[i];
        map.C[i] = C[i];
        map.D[i] = 0;
      }
    #endif
      return map.X;
    }

    void setup()
    {
      Serial.begin(9600);
      while (!Serial);
      uint8_t a[] = { 0x12, 0x34 };
      uint8_t b[] = { 0x56, 0x78 };
      uint8_t c[] = { 0x9a, 0xbc };
      uint64_t res = foo(a, b, c);
      Serial.print((uint32_t) (res >> 32), HEX);
      Serial.print((uint32_t) res, HEX);
    }

    void loop()
    {
    }

Cheers!

body:
    uint64_t foo(uint8_t* A, uint8_t* B, uint8_t* C)
    {
        uint64_t aux = 0;
        aux = A[0];
        aux <<= 8;
        aux |= A[1];
        aux <<= 8;
        aux |= B[0];
        aux <<= 8;
        aux |= B[1];
        aux <<= 8;
        aux |= C[0];
        aux <<= 8;
        aux |= C[1];
        return aux;
    }

following sample code:

      uint8_t a[] = { 0x12, 0x34 };
      uint8_t b[] = { 0x56, 0x78 };
      uint8_t c[] = { 0x9a, 0xbc };

      uint64_t result = foo(a, b, c);

      std::cout << std::hex << result;

returns `123456789abc`, try [the code here](https://onlinegdb.com/S15ZvIfmQ), excluding the std::out part, the same code will run on arduino without any problem


body:
I have an Arduino IDE 1.8.5 setup (installed from the ZIP file) which I use to work exclusively with a single board. Every time the IDE is restarted, the first compilation takes much longer than subsequent ones. Apparently, the reason is that Arduino IDE rebuilds the core library:

>Archiving built core (caching) in: C:\Users\User\AppData\Local\Temp\arduino_cache_976772\core\core_arduino_avr_mega_cpu_atmega2560_82177ffe36573ad451e992f583fff1d1.a

Is there a way to prevent that and make the IDE keep the cached core library across restarts? I have the "Aggressively cache compiled core" option checked, but it doesn't seem to help.

title: Prevent Arduino IDE from rebuilding the core library after every restart

Answers: 0


body: I am making a project for my college in which I need to measure the rpm of the motor and show the real-time clock on the 128x64 GLCD simultaneously but when I run the project it only shows one thing at a time. is there any method to show both of them simultaneously I am not putting any code because I just compile my hall sensor separately and rtc code separately

title: Arduino code to run 2 thing simultaneously

Answers: 1

body:
Arduino Microprocessors are mostly single core devices and thus are unable to do more than one thing at a time.
The trick is to write code efficiently so it looks like several things are happening at the same time but in reality they just happen very quickly.
The LCD only needs to show time every second and displaying RPM every second should be enough so to get both to happen within a second should be possible.


body:
Please I'm new to Arduino and I need assistance. I'm working on a project which makes use of the ultrasonic sensor to make a certain pin high if a certain distance is attained. When I used the USB port to power it up it worked fine. When I use external power(tried two different 9V microphone battery) it's not giving desired result. Now I want to try using just the Atmega328P on the board externally(separately from the Arduino).

**Questions**

1. What could be the cause of the malfunction when I use external 9V battery
2. what voltage should I connect to the VCC of the Atmega cos I'm scared of damaging it.
3. Am I going to power the ultrasonic sensor with an entirely different source from the VCC or I can tap from that same VCC source.
4. Any other information I need to know using the ATmega on its own

title: Powering Atmega328P-Pu externally

Answers: 2

body:
**1.8 - 5.5V (max)**

The datasheet ([http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Summary.pdf][1]) will tell you that input Voltage is: 1.8 - 5.5V

That's max of 5.5V so don't use 9V battery without a voltage divider.
To power the chip all you need is voltage to Pin 7 and GND to PIN 8.

**16Mhz Crystal Most Likely Required**

However, to get it to work after removing the chip from an Arduino Uno board you will also need a 16Mhz Crystal on pins 9 & 10.  You will also need two 22pF capacitors on pins 9 & 10, each connected to ground.

I've written this all up with pictures at my blog: [http://raddev.us/arduino/post/2018/07/03/arduino-uno-using-your-atmega328p-u-as-stand-alone][2]

Your final circuit will look something like the following (from my blog article):
[![with crystal][3]][3]

Without the Crystal you will most likely find that your sketches don't seem to run.

**Note**: The red LED is connected just as a blink test (more on that in the article).

  [1]: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Summary.pdf
  [2]: http://raddev.us/arduino/post/2018/07/03/arduino-uno-using-your-atmega328p-u-as-stand-alone
  [3]: https://i.stack.imgur.com/usIUK.png

body:
What you need is a voltage [regulator][1]! There are many options to choose from linear regulators to buck (or boost) [DC-DC converter][2]. You can buy them from various sources as well.

> What could be the cause of the malfunction when I use external 9V battery?

The ATMega can only handle 5V maximum, using 9V will either destroy it or engage protection circuitry that will prevent the chip from operating and being damaged.

> What voltage should I connect to the VCC of the Atmega?.

Most of the time an ATMega is powered with 5V, but depending on the clock frequency they can operate at lower voltages, the datasheet will have the details.

> Am I going to power the ultrasonic sensor with an entirely different source from the VCC or I can tap from that same VCC source?

With the appropriate choice of powersupply you can power both the AVR chip and your sensor with the same power supply.

>  Any other information I need to know using the ATmega on its own?

The datasheet will contain all you need to know, but if you want to use the Arduino tool chain you will need to:

 - Use an external crystal
 - Burn the Arduino (or AvrDUDE) bootloader

  [1]: https://en.wikipedia.org/wiki/Voltage_regulator
  [2]: https://en.wikipedia.org/wiki/DC-to-DC_converter


body:
I am trying to count files. I have one hidden file from Windows10 so i am doing "-1" but I want to open the last file and can't work out how, any help? Please, Thanks

    #include <SD.h>
    int entryCount = 0;
    File root;
    int total = 0;
    int Lfile = 0;
    void setup()
    {
      Serial.begin(9600);
      pinMode(10, OUTPUT);
      SD.begin(4);
      root = SD.open("/");
      printDirectory(root, 0);
      root.close();
      Serial.println();
      Serial.print(total-1);
      Lfile = total-1;

      File dataFile = SD.open(Lfile);
      // if the file is available, write to it:
      if (dataFile) {
        while (dataFile.available()) {
          Serial.write(dataFile.read());
        }
        dataFile.close();
      }
      // if the file isn't open, pop up an error:
      else {
        Serial.println();
        Serial.println("error opening last file");
      }
    }

    void loop()
    {
      // nothing happens after setup finishes.
    }

    void printDirectory(File dir, int numTabs)
    {
      while (true)
      {
        File entry = dir.openNextFile();
        if (! entry)
        {
          if (numTabs == 0)
          return;
        }
        for (uint8_t i = 0; i < numTabs; i++)
          Serial.print('\t');
        Serial.println(entry.name());
        total = entryCount;

        Serial.print(entryCount++);

        Serial.print('\t');

        entry.close();

      }
    }

title: Arduino SD count files and open last, How to?

Answers: 1

body:
Consider using the [exist() method][1] found in the [SD.h library][2] you already are including in your program.  Assuming you will create no more than 99 files and the last file created will have the highest 2 digit value as part of its name, test for the existence of the file log99.txt.  If not found, decrement the 2 digit number and test for the existence of file log98.txt.  Repeat this process until you find the newest file created.

  [1]: https://www.arduino.cc/en/Reference/SDexists
  [2]: https://www.arduino.cc/en/Reference/SD


body:
Is there a way to make the Arduino wait until all the serial data has been received? Say I send a 32 byte long string over serial (the length is actually random), how would I make my Arduino wait till all 32 bytes have been received?

If I execute `Serial.readBytes` straight away, it only reads one char. At the moment I'm using delay, but I'm worried that it is wasting time on the Arduino, as I would like it to be processed straight away. What I want to happen is I plug in my Arduino, type in the name of an input and output file, and it will start copying the input file into the output file. I don't want to re-upload every time I want to change files, so I would like to select over serial which ones to use. However, sometimes there will be no `\r` or `\n` sent at the end, which cuts off some of the file name.

Here is my code:

    #include <SoftReset.h>
    #include <SPI.h>
    #include <SdFat.h>
    #define csPin 4

    SdFat SD;
    File sourceFile;
    File outputFile;

    int bufSize;
    uint32_t lastPos = 0, timeLast, timeNow;
    //fix this (error: deprecated conversion from string constant to 'char*')
    //char *outputFileName = "output.wav";
    #define outputFileName "output.wav"
    byte avail;

    void setup() {
      // Open serial communications and wait for port to open:
      Serial.begin(115200);
      while (!Serial) {
      }
      Serial.print(F("Initializing SD card..."));

      // see if the card is present and can be initialized:
      if (!SD.begin(csPin, SPI_FULL_SPEED)) {
        Serial.println(F("Card failed, or not present"));
        soft_restart();
      }
      Serial.println("Card initialized.");
    enterInputFileName:
      Serial.println(F("Enter input file name:"));
      while (!Serial.available()); // wait till serial available
      delay(100);
      avail = Serial.available() - 2; // extra '\n' & '\r' that we dont want
      char inbuf[avail];
      Serial.readBytes(inbuf, avail);
      Serial.read(); // remove '\n' from buffer
      Serial.read(); //remove '\r' from buffer
      inbuf[avail] = '\0';

      char inputFileName[avail];
      strcpy(inputFileName, inbuf);
    confirmInputFileName:
      Serial.print(F("Select file '"));
      Serial.print(inputFileName);
      Serial.println(F("'? Y/N"));

      while (!Serial.available()); // wait till serial available
      delay(100); //wait for all chars to be recieved
      avail = Serial.available() - 2;
      if (avail > 1) {
        Serial.println(F("Enter 1 character"));
        while (Serial.available()) { //clear serial buffer
          Serial.read();
        }
        goto confirmInputFileName;
      }
      char confirm = Serial.read();
      Serial.read();
      Serial.read();
      switch (confirm) {
        case 'Y': break;
        case 'y': break;
        case 'N': goto enterInputFileName; break;
        case 'n': goto enterInputFileName; break;
        default: Serial.println(F("Enter Y/N")); goto confirmInputFileName; break;
      }
      //up to here works
      Serial.println(SD.exists(inputFileName));

      SD.remove(outputFileName);
      outputFile = SD.open(outputFileName, FILE_WRITE);
      outputFile.close();
      //read source and write to output
      sourceFile = SD.open(inputFileName);
      timeLast = micros();
      if (sourceFile) {
        pinMode(LED_BUILTIN, OUTPUT);
        digitalWrite(LED_BUILTIN, HIGH);
        Serial.println(F("Copying"));
        while (sourceFile.available()) {
          //make buffer size 50% of free ram, or amount of bytes left if smaller
          bufSize = min((freeRam() * 0.5 ), sourceFile.available());
          byte data[bufSize];
          sourceFile.readBytes(data, bufSize);
          lastPos = sourceFile.position();
          sourceFile.close();
          outputFile = SD.open(outputFileName, O_APPEND | O_WRITE);
          outputFile.write(data, bufSize);
          printStats();
          outputFile.close();
          sourceFile = SD.open(inputFileName);
          sourceFile.seek(lastPos);
        }
        sourceFile.close();
        outputFile.close();
        Serial.println(F("Finished"));
        unsigned int sec = millis() / 1000;
        unsigned int mins = sec / 60;
        sec -= mins * 60;
        Serial.print(F("Time taken: "));
        Serial.print(mins);
        Serial.print(':');
        Serial.print(sec);
        Serial.print(F("Speed: "));
        Serial.print((sourceFile.size() / 1000) / (millis() / 1000));
        Serial.print(F(" KB/s"));
      }
      // if the file isn't open, pop up an error:
      else {
        Serial.print("error opening files");
        SD.initErrorHalt();
      }
    }

    void loop() {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(200);
      digitalWrite(LED_BUILTIN, LOW);
      delay(200);
    }

    int freeRam () {
      extern int __heap_start, *__brkval;
      int v;
      return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
    }

    void printStats() {
      timeNow = micros();
      uint32_t timeTaken = timeNow - timeLast;
      float sent = sourceFile.position() / 1000.0;
      float fileSize = sourceFile.size() / 1000.0;
      float left = fileSize - sent;
      float speed;
      speed = 1000000UL / timeTaken * bufSize;
      speed /= 1000;
      unsigned int sec = millis() / 1000;
      unsigned int mins = sec / 60;
      sec -= mins * 60;
      int estSec = (left / speed);
      int estMin = estSec / 60;
      estSec -= estMin * 60;
      Serial.print(F("\tSent (KB): ")); Serial.print(sent);
      Serial.print(F("\tLeft (KB): ")); Serial.print(left);
      Serial.print(F("\tSize (KB): ")); Serial.print(fileSize);
      Serial.print(F("\tTime: "));      Serial.print(mins); Serial.print(':'); Serial.print(sec);
      Serial.print(F("\tSpeed (KB/sec): "));     Serial.print(speed);
      Serial.print(F("\tFree: "));      Serial.print(freeRam() - bufSize);
      Serial.print(F("\tBuf: "));       Serial.print(bufSize);
      Serial.print(F("\tEST: "));       Serial.print(estMin); Serial.print(':'); Serial.print(estSec);
      //todo fix this line
      //Serial.print(F("\tExists(I,O): ")); Serial.print(SD.exists(inputFileName)); Serial.print(SD.exists(outputFileName));
      Serial.print('\n');
      timeLast = micros();
    }

title: Wait for ALL serial data to be received

Answers: 3

body:
You need to format the message so that the receiver knows where the message ends and a new one begins.

Then on he receiving end you fill a buffer until a full message is received and then handle the message.

A more advanced tactic is to process the bytes as you receive them. This requires that you build a statemachine but means you don't have to store a copy of the entire message.

body:
I was concerned about the same thing recently when I worked on a project that would read serial data (received on a Bluetooth HC-05).

My loop() does a lot of work for my project ([Never Type A Password Again (Arduino-driven Touchscreen Device @ CodeProject.com][1] ) but reading the serial data is a big part of the work to do also.

I implemented the following code and it has been literally running for weeks now with no problems.

    if (Serial1.available() > 0) {
        incomingByte = Serial1.read();
        while (incomingByte > 0){
          if (incomingByte == 0x01){
            Keyboard.press(KEY_LEFT_CTRL);
            Keyboard.press(KEY_LEFT_ALT);
            Keyboard.write(KEY_DELETE);
            Keyboard.release(KEY_LEFT_ALT);
            Keyboard.release(KEY_LEFT_CTRL);
          }
          else{
             Keyboard.write(incomingByte);
          }
          incomingByte = Serial1.read();
        }
      }

You can see that it reads bytes while they are available which might lead you to think it might lock up, but it handles it very well.

**Quite A Bit Of Work**

It does quite a bit of work because it is capturing any bytes that come across Bluetooth (and then it types them on the connected computer -- that's a long story, check out the article for more).

**Quite A Few Bytes**

It also reads at least 64 bytes (password length + special Control char bytes) but it handles it quite well.

  [1]: https://www.codeproject.com/Articles/1249134/Never-Type-A-Password-Again-The-Continuing-Saga

body:
after source code was add to the question:

you use the readBytes function wrong. if you set the size parameter to count of available bytes it will read the count of available bytes.

allocate a buffer and set the second parameter as the buffer size. the readBytes will try to fill the buffer, waiting max one second for the next character, which is enough to read the complete line sent from Serial Monitor.

    if (Serial.available()) {
      char buff[50];
      int length = Serial.readBytes(buff, sizeof(buff) - 1);
      buff[length] = 0; // terminating zero of c-string
      Serial.println(buff);
    }

note: readBytes will wait one second after the last character received. better is to use readBytesUntil with expected terminator. or you can set smaller timeout on Serial with Serial.setTimeout(200)


body:
i have a code that shot a single pulse from pin D5 timer 0 (based on josh levine code), it works fine. the code is below

    #define OSP_SET_WIDTH(cycles) (OCR0B = 0xff-(cycles-1))
    void osp_setup(uint8_t cycles) {
        TCCR0B =  0;
        TCNT0 = 0x00;
        OCR0A = 0;
        OSP_SET_WIDTH(cycles);
        TCCR0A = _BV(COM0B0) | _BV(COM0B1) | _BV(WGM00) | _BV(WGM01);
        TCCR0B = _BV(WGM02) | _BV(CS00);
        DDRD |= _BV(5);
    }

    void osp_setup() {
        osp_setup(1);
    }

    #define OSP_FIRE() (TCNT0 = OCR0B - 1)
    #define OSP_INPROGRESS() (TCNT0>0)
    #define OSP_SET_AND_FIRE(cycles) {uint8_t m=0xff-(cycles-1); OCR0B=m;TCNT0 =m-1;}

    void setup()
    {
        osp_setup();
    }

    void loop()
    {
        OSP_SET_AND_FIRE(4);
        delayMicroseconds(20);
    }

however, i want to generate the same pulse in pin 10 or 9 which is timer 1, so a change the code a bit just like this

    #define OSP_SET_WIDTH(cycles) (OCR1B = 0xff-(cycles-1))
    void osp_setup(uint8_t cycles) {
        TCCR1B =  0;
        TCNT1 = 0x00;
        OCR1A = 0;
        OSP_SET_WIDTH(cycles);
        TCCR1A = _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10) | _BV(WGM11);
        TCCR1B = _BV(WGM12) | _BV(CS10);
        DDRD |= _BV(10);
    }

    void osp_setup() {
        osp_setup(1);
    }

    #define OSP_FIRE() (TCNT1 = OCR1B - 1)
    #define OSP_INPROGRESS() (TCNT1>0)
    #define OSP_SET_AND_FIRE(cycles) {uint8_t m=0xff-(cycles-1); OCR1B=m;TCNT1 =m-1;}

    void setup()
    {
        osp_setup();
    }

    void loop()
    {
        OSP_SET_AND_FIRE(4);
        delayMicroseconds(20);
    }

but it doesn't work, and i am stuck, any help? i use arduino nano

Thank you

title: Generate single pulse from timer 1 in arduino nano

Answers: 1

body:
Timer1 has a few extra features, so you need to set the registers slightly differently from timer0 (or timer2). You need to also set the WGM13 bit in the TCCR1B register.

Since timer1 is a 16 bit timer, you need to change OSP_SET_AND_FIRE to also use 16 bits.

Lastly; Arduino pin 10 is port B, not port D.

    #define OSP_SET_WIDTH(cycles) (OCR1B = 0xff-(cycles-1))
    void osp_setup(uint8_t cycles) {
        TCCR1A = 0;
        TCCR1B = 0;
        TCNT1 = 0x00;
        OCR1A = 0;
        OSP_SET_WIDTH(cycles);
        TCCR1A = _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10) | _BV(WGM11);
        TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
        DDRB |= _BV(DDB2);//pin 10; PB2
    }

    void osp_setup() {
        osp_setup(1);
    }

    #define OSP_FIRE() (TCNT1 = OCR1B - 1)
    #define OSP_INPROGRESS() (TCNT1>0)
    #define OSP_SET_AND_FIRE(cycles) {uint16_t m=0xffff-(cycles-1); OCR1B=m;TCNT1 =m-1;}

    void setup()
    {
        osp_setup();
    }

    void loop()
    {
        OSP_SET_AND_FIRE(4);
        delayMicroseconds(20);
    }


body:
I am pretty new to Arduino programming and wanted to learn how to connect an ESP8266 generic WiFi module to an Arduino Uno using the ESP-01 Adapter shown in the image below.

I tried doing it on my own while connecting the Vcc, GND, Tx and Rx pins of the adapter to the 5V, GND, Tx and Rx of the Arduino Uno respectively but was getting the following error while trying to upload the sketch:

> warning espcomm_sync failed
>
> error espcomm_open failed
>
> error espcomm_upload_mem failed

To the best of my knowledge there is no tutorial on the internet that explains about the above mentioned adapter and its interfacing with the wifi module in detail. It would be a great help if someone could please guide me through the process so as to convert my Arduino into a server.

[![ESP-01 Adapter][1]][1]

  [1]: https://i.stack.imgur.com/PbJjQ.jpg "ESP-01 Adapter"

title: How to connect an ESP8266 using an ESP-01 adapter to an Arduino Uno?

Answers: 2

body:
Recommended [tutorial][1]

you can't flash an esp-01 module with this adapter, unless you find a way to connect io 0 to ground in this setup

[![enter image description here][3]][3]

I have this type of adapter with esp8266 glued. I can't recommend this type of adapter boards. Easier is to use a development board like Wemos or NodeMCU with on-board USB adapter. And they are cheap.

The adapter has the esp-01 2x6 header J2 but the io 0 and io 2 pins were not connected on my version. I patched io 0 to JP2 header to be able to flash the module. On the picture you see a paperclip jumper connecting GPIO0 to ground.

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

  [1]: https://tttapa.github.io/ESP8266/Chap01 - ESP8266.html
  [2]: https://i.stack.imgur.com/3lcdB.jpg
  [3]: https://i.stack.imgur.com/iHUgi.jpg

body:
> ...connecting the Vcc, GND, Tx and Rx pins of the adapter to the 5V,
> GND, Tx and Rx of the Arduino Uno respectively...

At least one issue is the serial connections. Rx and Tx need to be cross-connected with whichever Arduino pins you are connecting to the ESP. Using the Arduino's built-in UART, Arduino pin #s 0 and 1, cannot work for uploading (to either board) since those pins are used to communicate with your PC.

If you are trying to upload to the Arduino, try removing the ESP adapter board during the upload. Even with that, communicating at run-time from the Arduino to the ESP (with it plugged back in, of course) may run into interference from the Arduino's 16U2 chip (serial <-> USB processor) which is hard-wired to those pins. And if it does work at run-time, you will have to forego serial communication to/from your PC, which uses those same pins.

The alternative is to use the SoftwareSerial library in your code, which will let you select two other Arduino pins as a second "software UART" to communicate to/from the ESP. This route come with it's own initial-setup complexities - you'll first have to change your ESP's default baud rate to 9600, about the maximum that SoftwareSerial can reliably receive. See [my post about how to do this][1]. To implement it, you'll need a short sketch that continuously tests Arduino's terminal for an available character and sends any to the ESP, and likewise tests the SoftwareSerial and sends to the Arduino's terminal.

  [1]: https://arduino.stackexchange.com/questions/18647/linking-arduino-nano-with-esp8266-wifi-module/24961#24961


body:
I am using a Netafim M-Series flow meter interfaced with a UC-32 Arduino. The goal of this is to create a pulse counter than in turn will allow us to determine flow rate in the meter. (1 US gallon per pulse for this model.)

I am using a relatively simple program to test my wiring and the flow meter's connection to the UC-32. I will include it here:

    int pin = 30;
    volatile unsigned int pulse;
    const int pulses_per_litre = 450;

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

      pinMode(pin, INPUT);
      attachInterrupt(0, count_pulse, RISING);
    }

    void loop()
    {
      pulse = 0;
      interrupts();
      delay(1000);
      noInterrupts();

      Serial.print("Pulses per second: ");
      Serial.println(pulse);
    }

    void count_pulse()
    {
      pulse++;
    }

Code was obtained by a source online, since I will make my own to match my specific needs later on. The problem is, no matter how much I modify this code, I receive 0 pulses (even when blowing air into the meter). I have therefore narrowed down the problem to wiring.

I am using a small breadboard with a 1 kOhm Resistor. The flow meter requires 12v input that is supplied by a barrel jack power supply into the UC-32. I will show an image of my circuit. From what I can see, this should be working, but I feel like I'm sort of going insane looking over and over this circuit so I wanted to get an outside opinion.

[![Breadboard][1]][1]
[![UC32][2]][2]

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

Sorry about the large sizes images, but to me, it is a simple circuit that should work. I could be very wrong. Does anyone with perhaps experience with this sort of flow meter see any problems with my code/circuit?

title: Pulse counter to measure flow-rate: 0 Pulse issues

Answers: 1

body: Fixed, wow. Sometimes typing out your problem helps answer the question. Resistor position was wrong, and adjusting the Vin wire.


body:
I've connected a 5-way tactile switch to a ESP8266 module and am using the Arduino IDE to create an automatically updating web server that displays the direction that the button is pressed in when pressed. Currently the webpage displays the first direction that the button was pressed in but does not update the page after I press the button several more times. Below is my code:

    #include <ESP8266WiFi.h>
    #include <WiFiClient.h>
    #include <ESP8266WebServer.h>
    #include <ESP8266mDNS.h>

    //ssid and password info, ommitted here for obvious reasons

    int upPin = 5;
    int leftPin = 4;
    int centerPin = 0;
    int rightPin = 2;
    int downPin = 14;

    ESP8266WebServer server ( 80 );

    void handleRoot() {
        server.send(200, "text/html", "\
      \
        <meta http-equiv='refresh' content='1'/>\
      \
      \
      \
    ");   // Send HTTP status 200 (Ok) and send some text to the
    browser/client
    }

    void setup(){
     Serial.begin ( 115200 );
     WiFi.mode ( WIFI_STA );
     WiFi.begin ( ssid, password );

     server.on ( "/", handleRoot );
     server.on ("/", button );
     server.begin();

    void loop(void){
      server.handleClient();
      button();
    }

    void button(){
      if (digitalRead(rightPin) == LOW)
      {
        server.send(200, "text/html", "
*RIGHT#
");
        delay(10);
      }

      if (digitalRead(leftPin) == LOW)
      {
        server.send(200, "text/html", "
*LEFT#
");
        delay(10);
      }

      if (digitalRead(upPin) == LOW)
      {
        server.send(200, "text/html", "
*UP#
");
        delay(10);
      }

      if (digitalRead(downPin) == LOW)
      {
        server.send(200, "text/html", "
*DOWN#
");
        delay(10);
      }

      if (digitalRead(centerPin) == LOW)
      {
        server.send(200, "text/html", "
*CENTER#
");
        delay(10);
      }

    }

title: Updating Server using ESp8266 with Direction Button Pressed IN

Answers: 1

body: I changed the code so that the button function runs with "/" and took out the server.on("/", handleRoot) line, thanks to @Juraj. *Sigh*


body:
I have an Arduino Mega 2560 that I need to connect 4 MPU 6050/Gy 521's to.

I found some resources on the Mega and Uno, however I'm having trouble piecing them together.

This resource gives great detail for connecting a single MPU to a mega.
http://dummyscodes.blogspot.com/2014/07/mpu6050-gy-521-breakout-arduino-mega.html

This resource gives a trick for connecting multiple to an UNO.
https://playground.arduino.cc/Main/MPU-6050

My problem is that the wiring for the Uno and Mega are different. The resource I have for the UNO describes using the MPU AD0 (output) connecting it to different output pins for each MPU. The resource talking about the MEGA doesn't even use the AD0, and uses INT but I'm not sure if I can use the same concept.

Plus, I still don't actually understand how to connect/what other pins to use for the other 4.

I'm pretty new to Arduino, definitely new to anything with wiring.

Please help! I'm really confused about using multiple together, and about how to properly wire them.

title: Wiring for Arduino Mega and multiple MPU 6050/Gy 521?

Answers: 2

body:
MPU-6050 uses I2C for comm's, yes?
Connect all the SCLs in parallel to the Mega with a 4.7K, or 3.3K, pullup resistor. Same for the SDAs. I2C is D20, D21 (or D21, D22) on the Mega.

The MPU-6050 has an A0 pin to select from one of two addresses, let's call them Add0 and Add1 for simplicilty.
Connect each MPU-6050 A0 pin to a unique Mega pin.  When none are being addressed, have each Mega output high. When one MPU-6050 is to be accessed, take that device's A0 pin low and communicate with it using Add0. The other's will be looking for communications at Add1 and thus will not respond.

If the MPU6050 is a 3.3V device, then you should also remove the pullup resistor network package on the Mega that pulls SCL/SDA to 5V.  There are 2 pullups in a very little 8-pin package, the other 2 are not used. Connect the 3.3K or 4.7K pullup resistors discussed above to 3.3V.

----

This is the part, RN1, on the Mega R3 board. It may not be marked as such on the board. Remove it, or cut the traces next to the pad legs, one on the left side (connects to pin 3), one on the top (connects to pin 2).
[![enter image description here][1]][1]
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/RJGiT.png
  [2]: https://i.stack.imgur.com/feVsT.png

body:
CrossRoads' answer using the address selection pin on your MPU modules is excellent. It does tie up a GPIO line for each MPU you want to address however.

(If you are using a Mega 2560 this might not be an issue since they have tons of GPIO lines.)

You could also get a I2C addressing multiplexer. Adafruit and Sparkfun both offer them Example: https://www.adafruit.com/product/2717?gclid=EAIaIQobChMItYnah7zB4QIVAoTICh1JlAk3EAQYASABEgK7hvD_BwE

That one will multiplex up to 8 I2C devices with the same address, and doesn't require any additional pins. You send a single I2C command to it to select one of your 8 devices.

I don't know if anybody makes an I2C multiplexer that also does voltage conversion. Seems like that would be handy.


body:
I've created a code for ESP8266 12E with Arduino IDE, in which it'll operate as "**Station Mode**" or "**Access Point Mode**" on Wifi, depending on the situation. Everything works fine except when device was configured as Access Point, even when I turn off device and then turn on again and force the Wifi initialization as "Station Mode", the Access Point network stays active.

Example: Let's suppose that I turned on the ESP8266 and initialized the Wifi as Access Point, and named the wifi network as "MY_WIFI_TEST". Let's assume now that I turned off the ESP8266 and forced it to turn on as "Station Mode". The ESP8266 typically connects to my network (the network of my gateway router 192.168.1.1), but keeps the network "MY_WIFI_TEST" active (the prior network as access point). You can not connect to this network, but it remains active.

How can I turn off or stop Access Point network?

My test code:

```c++
    #include <ESP8266WiFi.h>

    bool access_point_init(){
     // Access Point Mode

       Serial.begin(115200);
       IPAddress ip(192,168,1,254);
       IPAddress gateway(192,168,1,1);
       IPAddress subnet(255,255,255,0);
       char* ssid     = "myssidname";
       char* password = "12345678";

       WiFi.softAPConfig(ip, gateway, subnet);
       bool ret = WiFi.softAP(ssid, password);

       return ret;
    }

    void wifi_station_init(){

     // Station Mode
     Serial.begin(115200);
       Serial.printf("\n");

       WiFi.begin(net_ssid, net_pwd_ssid);

       IPAddress ip(192,168,1,10);
       IPAddress gateway(192,168,1,1);
       IPAddress subnet(255,255,255,0);

     WiFi.config(ip, gateway, subnet);

       k = 0;
       while ((WiFi.status() != WL_CONNECTED) && (k < 80)){
          delay(250);
          Serial.print('.');
          k++;
       }

       Serial.printf("\n");
       Serial.printf("IP address: ");
       Serial.println(WiFi.localIP());
    }

    void setup()
    {
     bool my_condition = false;
     //...
     // my_condition = myLoadFunction();
     //...

       if (my_condition) {
      access_point_init();
       } else {
          wifi_station_init();
       }
    }
```

title: How to turn off or stop Access Point network in ESP8266?

Answers: 3

body:
I've already solved, by using a function of the library Wifi, specific for the connections in "Access Point" mode:

    WiFi.softAPdisconnect (true);

Reference:
[softapdisconnect][1]

  [1]: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/soft-access-point-class.html#softapdisconnect

body:
I fixed this by adding below command before starting the accesspoint.

````  WiFi.mode(WIFI_AP); ````

body:
I was trying to turn off the softAP in the new Arduino Uno R4 Wifi so I could rename it and restart it. I put a changing sensor reading in AP name so I can see the value of it by just doing a network scan without actually connecting to it.

The wifi.h lib for UNO R4 doesn't implement SOFTAPDISCONNECT. In the example AP_SIMPLEWEB server I found adding the following function shuts down the AP and allows restarting with a different name.

```
void endAccessPoint() {
  using namespace std;
  string res = "";
  modem.begin();
  modem.write(string(PROMPT(_DISCONNECTSOFTAP)),res,"%s%d\r\n" ,CMD_WRITE(_DISCONNECTSOFTAP),1);
}
```


body:
<!-- language: lang-cpp -->

    #include <Arduino.h>
    #include <ESP8266WiFi.h>
    #include <ESP8266WiFiMulti.h>
    #include <ArduinoJson.h>
    #include <ESP8266HTTPClient.h>
    #define USE_SERIAL Serial

    ESP8266WiFiMulti WiFiMulti;
    String url = "http://192.168.31.170/api/mode/qwertyui";

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

      USE_SERIAL.println();
      USE_SERIAL.println();
      USE_SERIAL.println();

      for (uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
      }

      WiFi.mode(WIFI_STA);
      WiFiMulti.addAP("Robotics Incubator", "XXXXXXX");
    }

    void loop() {
      // wait for WiFi connection
      if ((WiFiMulti.run() == WL_CONNECTED)) {
        HTTPClient http;
        http.begin(url); //HTTP
        int httpCode = http.GET();

        if (httpCode == 200) {
          // Parsing
          const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
          DynamicJsonBuffer jsonBuffer(bufferSize);  //This was not declared error.
          JsonObject& root = jsonBuffer.parseObject(http.getString());
          // Parameters
          int Mode = root["mode"]; // 1
          Serial.print("Name:");
          Serial.println(Mode);
        }
        http.end();
      }

      if (Serial.available()) {
        url = Serial.readString();
      }
      delay(100);
    }

How can I solve this problem?
I followed this tutorial - [ESP8266: Parsing JSON][1]

  [1]: http://www.instructables.com/id/ESP8266-Parsing-JSON/

title: NodeMCU (Arduino IDE) 'DynamicJsonBuffer' was not declared in this scope

Answers: 2

body:
This error is caused by using a 6.x.x version of the ArduinoJson library with code that was written for a pre-6.x.x version of the library.

You have two options to solve the problem:

### A. Downgrade the library to a version that is compatible with your code
For now, this is probably the best option because the 6.x.x version of the ArduinoJson is still in beta so it makes sense to wait until the new API is stabilized before porting your code. This is even recommended by the ArduinoJson developers:

https://arduinojson.org/v5/faq/error-jsonbuffer-was-not-declared-in-this-scope/

1. Sketch > Include Library > Manage Libraries...
1. Wait for the download to finish.
1. In the "Filter your search..." box, type: "arduinojson".
1. Click on "ArduinoJson by Benoit Blanchon".
1. From the "Select version" dropdown menu, select "Version 5.13.2".
1. Click "Update". Wait for the update to finish.
1. Click "Close".

Now your code will compile. If you have **File > Preferences > Check for updates on startup** enabled, you will continue to get updatable library notification for the ArduinoJson library but you need to refrain from updating back to a 6.x.x version or the error will come back.

### B. Update your code to be compatible with the 6.x.x version of the ArduinoJson library

In this case you need to modify your deserialization code to use the new `DynamicJsonDocument` instead of the old `DynamicJsonBuffer`:

<!-- language: lang-cpp -->

    if (httpCode == 200) {
      // Parsing
      const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
      DynamicJsonDocument jsonDocument(bufferSize);
      DeserializationError error = deserializeJson(jsonDocument, http.getString());
      if (error) {
        Serial.println("There was an error while deserializing");
      }
      else {
        JsonObject root = jsonDocument.as<JsonObject>();
        // Parameters
        int Mode = root["mode"]; // 1
        Serial.print("Name:");
        Serial.println(Mode);
      }
    }

You can get more details about this here:

https://arduinojson.org/v6/doc/upgrade/

body:
This answer needs to be updated for anyone who visits here.
The 6.x.x is no longer in beta.
Simply update to the latest version. At the time of writing this answer the version id is 6.15.2. Updating to this will resolve the error.


body:
I have an analog or dumb RGB strip that I control with HTTP commands. I want to be able to make the strip fade between different colours when I call `http://XX.X.X.XXX/fade`. I want it to do this infinitely until another colour is set or it turns on or off. I have tried doing this with a while loop but I can no longer change the state of the light from fading. Does anyone know how to do this? I'll link my code below.

    //NodeMCU RGB-Controller for Homebridge & HomeKit (Siri)

    #include <ESP8266WiFi.h>

    #include <DNSServer.h>
    #include <ESP8266WebServer.h>

    #define redPin 13 //D7 - Red channel
    #define grnPin 12 //D6 - Green channel
    #define bluPin 14 //D5 - Blue channel

    #define max(a,b) ((a)>(b)?(a):(b))

    WiFiServer server(80); //Set server port

    String readString;           //String to hold incoming request
    String hexString = "FFFFFF"; //Define inititial color here (hex value), 080100 would be a calm warmtone i.e.

    int state;

    bool fading;

    int r;
    int g;
    int b;

    float R;
    float G;
    float B;

    int x;
    int V;

    ///// WiFi SETTINGS - Replace with your values /////////////////
    const char* ssid = "SSID";
    const char* password = "PASSWORD";
    IPAddress ip(XX,X,X,XXX);      // set a fixed IP for the NodeMCU
    IPAddress gateway(XX.X.X.X);  // Your router IP
    IPAddress subnet(XXX.XXX.XXX.X); // Subnet mask
    ////////////////////////////////////////////////////////////////////

    void WiFiStart() {
      Serial.print("Connecting to ");
      Serial.println(ssid);
      WiFi.begin(ssid, password);
      WiFi.config(ip, gateway, subnet); //Set a fixed IP. You can comment this out and set it in your router instead.
      while (WiFi.status() != WL_CONNECTED) {
        delay(100);
        Serial.print("_");
      }
      Serial.println();
      Serial.println("Done");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.println("");

      server.begin();
    }

    void allOff() {
      state = 0;
      for (float fade = 1.0; fade >= 0.0; fade -= 0.01) {
        analogWrite(redPin, map((r * fade), 0, 255, 0, 1023));
        analogWrite(grnPin, map((g * fade), 0, 255, 0, 1023));
        analogWrite(bluPin, map((b * fade), 0, 255, 0, 1023));
        delay(2);
      }
      // Set r/g/b to 0 so fade in is possible
      r = 0;
      b = 0;
      g = 0;
    }

    //Write requested hex-color to the pins
    void setHex() {
      const float STEPS = 100; // Change number of steps while fading (lower is faster)
      // Save old values of r/g/b
      byte oldR = r;
      byte oldG = g;
      byte oldB = b;
      long number = (long) strtol( &hexString[0], NULL, 16);
      r = number >> 16;
      g = number >> 8 & 0xFF;
      b = number & 0xFF;
      float deltaR = (r - oldR) / STEPS;
      float deltaG = (g - oldG) / STEPS;
      float deltaB = (b - oldB) / STEPS;
      // Fade to new colour
      for (float f = 0; f < STEPS; f++) {
        analogWrite(redPin, map((oldR + (deltaR * f)), 0, 255, 0, 1023));
        analogWrite(grnPin, map((oldG + (deltaG * f)), 0, 255, 0, 1023));
        analogWrite(bluPin, map((oldB + (deltaB * f)), 0, 255, 0, 1023));
        delay(2);
      }
      state = 1;
    }

    //Compute current brightness value
    void getV() {
      R = roundf(r/2.55);  //was (r/10.23);
      G = roundf(g/2.55);  //was (g/10.23);
      B = roundf(b/2.55);  //was (b/10.23);
      x = max(R,G);
      V = max(x, B);
    }

    //For serial debugging only
    void showValues() {
      Serial.print("Status on/off: ");
      Serial.println(state);
      Serial.print("RGB color: ");
      Serial.print(r);
      Serial.print(".");
      Serial.print(g);
      Serial.print(".");
      Serial.println(b);
      Serial.print("Hex color: ");
      Serial.println(hexString);
      getV();
      Serial.print("Brightness: ");
      Serial.println(V);
      Serial.println("");
    }

    void setup() {
      Serial.begin(9600);
      delay(1);
      pinMode(redPin, OUTPUT);
      pinMode(grnPin, OUTPUT);
      pinMode(bluPin, OUTPUT);
      WiFi.mode(WIFI_STA);
      WiFiStart();
      setHex();
    }

    void loop() {
      WiFiClient client = server.available();

      if (!client) {
        return;
      }

      while(client.connected() && !client.available()) {
        delay(1);
      }

      //Respond on certain Homebridge HTTP requests
      if (client) {
        while (client.connected()) {
          if (client.available()) {
            char c = client.read();
            if (readString.length() < 100) {
              readString += c;
            }
            if (c == '\n') {
              Serial.print("Request: ");
              Serial.println(readString);

              //Send reponse
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              client.println();

              //On
              if(readString.indexOf("on") >0) {
                setHex();
                showValues();
                fading = false;
              }

              //Off
              if(readString.indexOf("off") >0) {
                allOff();
                showValues();
                fading = false;
              }

              //Fade
              if(readString.indexOf("fade") >0) {
                fade();
                fading = true;
              }

              //Set color
              if(readString.indexOf("set") >0) {
                hexString = "";
                hexString = (readString.substring(9,15));
                setHex();
                showValues();
                fading = false;
              }

              //Status on/off
              if(readString.indexOf("status") >0) {
              client.println(state);
              }

              //Status color (hex)
              if(readString.indexOf("color") >0) {
              client.println(hexString);
              }

              //Status brightness (%)
              if(readString.indexOf("bright") >0) {
              getV();
              client.println(V);
              }

              delay(1);
              client.stop();
              readString="";
            }
          }
        }
      }
    }

    void fade() {
      while(fading == true){
        hexString = "000000";
        setHex();
        hexString = "FFFFFF";
        setHex();
        hexString = "FF0000";
        setHex();
        hexString = "008000";
        setHex();
        hexString = "0000FF";
        setHex();
        hexString = "FFFF00";
        setHex();
        hexString = "1E1E1E";
        setHex();
       }
     }

title: Fade effect analog RGB strip and NodeMCU

Answers: 1

body:
The variable `fading` cannot ever change, once you are in that `while` loop, since your code doesn't do it and you don't use interrupts either (And I don't know, if the library is supporting this). So the Arduino is stuck forever in this loop and will not respond to any interactions but resetting.

There are basically there are 2 different options for you (not counting the usage of a hypothetical interrupt capability of the Wifi library, as I don't know enough about the library):

 1. **Adding Wifi code to the `while` loop:** You can just add code, that watches the Wifi interface into the `while` loop and set the `fading` variable correspondingly. This is the easiest to program option.
 2. Rewrite your code (especially the `fade()` function) to be non-blocking, which means it will not block the execution of other code, but will only do something, when it is time to do so, and otherwise return from the function. You can achieve this by using the `millis()` function, which returns the milliseconds since the last startup/reset to use as a time source. Refer to the `BlinkWithoutDelay` example of the Arduino IDE. Also you can google for `millis()`; there are a ton of tutorials out there. When writing non-blocking code you might also want to implement a Finite State Machine (FSM). It's simpler as it sounds. You basically define a simple variable, which sets your current state (for example the states `fading`, `off`, `specific_color`, ...). In your `loop()` function you make a `switch(state_variable){ case` statement, where you insert code for every state in it's own `case`. Outside of the `switch` statement you can then check the Wifi interface and set the state variable correspondingly. If everything is written non-blocking it should work like a charm.


body:
I am working on arduino IDE and esp8266 nodemcu.
As i am going through the IDE I saw that there is a structure of void loop() and void setup() and all examples in the internet included defining the pinModes within the void setup() block.
I want to make a program where through mqtt or http the user will give input as to what type of device he/she wants to attach to the esp8266, so based on that i will have to set, INPUT/OUTPUT state on the following pins.

Now my initial idea was :

    void setup()
    {
        connectwifi();
    }

    void loop()
    {
       call_some_function();
    }

where `call_some_function()` will recieve the requirements from user over http. For example he wants a light on pin3, so `pinMode(pin3,OUTPUT);`

now what I wanted is that,
call the method - `call_some_function()` whenever the user needs to add an extra device to it, which means initally when we wanted to add 4 lights to esp8266, we will write

    pinMode(pin1,OUTPUT);
    pinMode(pin2,OUTPUT);
    pinMode(pin3,OUTPUT);
    pinMode(pin4,OUTPUT);

But now when I have a user defined input, my code will become something like this,

    call_some_function()
    {
         pin=(user gave me the pin no);
         state=(based on the device the server will send the state i.e IN/OUT);
         pinMode(pin,state);
    }

Now my question is , calling this function 4 times and writing `pinMode()` function 4 times will result in same thing or separate?
Also is this doable, like can i write like this?
I will be calling this function from `void loop()` instead if `void setup()`, since I continuously listen for user input,
Cause I cannot find any other way of making user specific input

title: Setting pinMode(pin,input/output) as per user requirement

Answers: 2

body:
> Now my question is , calling this function 4 times and writing pinMode() function 4 times will result in same thing or separate? Also is this doable, like can i write like this?

you can call pinMode anytime

And to add something more to pinMode. It is not just some preparation of the pin. It changes things for the connected circuit. Setting to INPUT lets the attached circuit rule. If there is a pull-up circuit the state will be HIGH, if pull-down LOW. INPUT_PULLUP holds the state HIGH but lets the attached circuit to pull it down. pinMode OUTPUT sets the pin LOW.

In two cases for now I use setting a pin to OUTPUT only for the time I want to control the attached circuit and the I set it back to INPUT. In first case I reset an esp8266 with EN pin connected by setting the pin LOW, then I let the external pull-up hold the EN pin HIGH. Second case is amplifier module for the tone() function. I set the pin to INPUT after tone() otherwise it catches noise.

body: `pinMode()` is usually called from `setup()` because in most cases, the pin mode remains the same throughout the run. Sometimes there is a reason to change it during the run, such as in your example, and you can call `pinMode()` at whenever is the appropriate time to do that.


body:
I am in between of project where i am getting string like "hello world" via Bluetooth to arduino I want to list this string into individual character so that I can call any of the character when required, this is not working i am getting only zeros in serial monitor
please suggest what i am doing wrong

    char s;
    int k[10];

    void setup () {
      Serial.begin(9600);
    }
    void loop () {
      if (Serial.available() > 0) {
        s = Serial.read();
      }
      k[10] = s;
      for (int x = 0; x < 10; x++) {
        Serial.println(k[x]);
        delay(200);
      }
    }

title: String input to character array

Answers: 1

body:
There are a few problems with your code sample:

----------

You check for `Serial.available()>0`, but then assume/grab only one character:

    if (Serial.available() > 0) {
      s = Serial.read();
    }

It is possible that the serial receive buffer has more than one byte waiting, but you only capture one.

----------

    k[10] = s;

You assign the captured character to the last element of the byte array, regardless of all else. This presents two main problems

 1. A C-style string must be terminated with a null character (`'\0'`), and you have immediately put real data in the position that should contain the terminating byte.
 2. There is no possible way that bytes 0-9 can ever have any data written to them by this code.

----------

Your code assumes that the entire string exists in `k[]` every time through `loop()`. Instead, you should assume that it might take hundreds or thousands of times through `loop()` just to finish receiving your string. The input string should have some kind of end-of-string marker like a newline (`'\n'`) or carriage-return (`'\r'`) (or both) so that your program can look for that and know when the input is fully received.

Below is a simple program that receives a string. Note that it has a portion labeled for when to process the recieved data. That block of code is only entered once a newline and/or carriage return are received.

    #DEFINE MAX_INPUT 90

    char inputBuffer[MAX_INPUT+1]; // Handles up to 90 bytes in a c-style string, with a null character termination.

    void setup()
    {
      Serial.begin(115200); // initialization
      inputBuffer[0] = '\0'; //Initialize string to emtpy.
      Serial.println("Begin:");
    }

    void loop() {

      if (Serial.available()>0)
      {
        char input = Serial.read();
        static int s_len; // static variables default to 0
        if (s_len>=MAX_INPUT) {
          // Have received already the maximum number of characters
          // Ignore all new input until line termination occurs
        } else if (input != '\n' && input != '\r') {
          inputBuffer[s_len++] = input;
        } else {
          // Have received a LF or CR character

          // INSERT YOUR CODE HERE TO PROCESS THE RECEIVED DATA //
          // YOU COULD COPY TO A NEW VARIABLE WITH strncpy() OR //
          // SET A FLAG TO SAY TO START SOME OTHER TASK         //
          Serial.print("RECEIVED MSG: ");
          Serial.println(inputBuffer);

          memset(inputBuffer, 0, sizeof(inputBuffer));
          s_len = 0;             // Reset input buffer here if you
                                 // have already copied the data.
                                 // If you don't reset here, then
                                 // you can't start receiving more
                                 // serial port data. This is your
                                 // 'software' serial buffer, contrast
                                 // with the hardware serial buffer.
        }
      }
    }


body:
I have a state machine program used to monitor sensors and activate relays that has been used and adapted on multiple machines and it typically performs exactly as needed. I am attempting to adapt the program to include an additional relay and two sensors and I can't figure out why the program won't update the states for two of the sensors added. All other sensors update and the program runs as intended until the program enters the state to check that the sensors have been interrupted. The final machine will use photo interrupters but I have bread boarded the circuit with both the sensors as well as using switches to attempt to debug the system.

Everything else works flawlessly on the breadboard and the program runs great save for the part where the program is waiting for the state of the sensors to read "BOTH_RSENSORS_LOW" on line 304 of the program. I have the serial monitor running to check the status of "RsensorState" that is updated every time line 302 runs. Within the main loop, "RsensorState" should be getting updated on line 174 which is supposed to be updated on line 437 where it should be returning the state based on the sensor inputs. The serial monitor shows no change to the state while changing the input on the pins attached to it. I have tested other pins as well in case they are shorted somehow to HIGH. I have the exact same sensors working fine to return the state of sensors 1 and 2. I have gone over the code and don't know what is missing. Every other block works great and as wanted. Perhaps I have a small syntax error that I am simply not seeing. I have attempted to lay out the program in as easy a format as I can and build the steps of the logic in blocks that are easy for me to navigate.

Board: Arduino DUE

Software: Arduino IDE 1.8.5

Includes the libraries Bounce2.h and LiquidCrystal.h

The device is designed to use a system of two buttons that need to be pressed within a specified time of each other. If at any point they are released they should turn off the relays and wait til both of them are released completely before being able to proceed again. The program is set up in 10 states to perform the functions of the machine.

CLEAR_SENSORS Turns off relay2 attached to a physical stop designed to align the part so the finished part can be slid through the machine and then checks to see if sensors 1 and 2 are not blocked meaning the part has been removed so the stop can then be be put back in place. Sensors 1 and two are on either side of the stop so that the stop will not be activated and hit the part as it is getting pushed through.

CHECK_SENSORS Turns back on relays and waits until a part is put back in and the first sensor can see that a part is in place. When it sees a part it moves to the next state.

WAIT_FOR_BOTH_LOW Checks the two safety buttons to be sure they are both released and the operator has not tried to short one out or has stuck something in the switch to hold it on. This is returned to any time the switches fail the timeout parameters.

WAIT_FOR_BUTTON Waits for a button to be pressed and goes into the next step.

ONE_PUSHED_WAIT_FOR_OTHER_BUTTON looks for the other button to be pressed within the specified time frame. If it is not then the program goes back to waiting for both to be released.

FINAL_CHECK checks to make sure the part has not been removed. If it has it goes back to waiting for the part to be put back in place and for all buttons to be released.

LOWER_RAILS checks to make sure the buttons are still being held and if so lowers an aligning and holding railing attached to Relay3

CHECK_RAIL_SENSORS checks 2 sensors to be sure they are both blocked and the railing is fully down. They are to act as limit sensors. This is the step the program gets stuck on.

SAFETY_WINDOW is a small time frame the machine waits until it turns on the relays and then after that time frame turns on relay1

RELAY_ON turns off the main relay1 and the holding relay3 if the buttons are released and turns them off after the time frame for the relays to run has expired. It then goes to the beginning where it waits for the part to be removed.

When I bypass the CHECK_RAIL_SENSORS step the whole things works flawlessly. I am stumped why that particular part isn't working. From what I can tell it has to do with the RsensorState not getting updated as expected like the other sensors are. sensorState updates and functions exactly as expected so I am not sure why RsensorState does not. Am I making a syntax error I am not aware of? I have gone through it a hundred times and maybe I am just not seeing it. All the components have been tested and function as expected. Here is the code:

    // This sketch reads inputs from two buttons and a sensor to turns on 2 relays
    // RelayPin2 is engaged until the end of the first relay's cycle
    // It requires that both buttons be pressed within a certain time of each other and held
    // A relay pin is then turned on for a specified period of time
    // RelayPin3 turns on and is verified by Sensors 3 and 4
    // RelayPin2 is turned off after the first relay pin has completed it's cycle
    // When the sensor is clear, RelayPin2 is turned on again
    // Both buttons must then be released again for another cycle to begin
    // A state machine is used, only to make it more clear what is going on.
    // Used with an Arduino DUE on Arduino 1.8.5 IDE
    // Original sketch found on https://arduino.stackexchange.com/questions/45584/state-machine-logic-problem-with-added-states-monitoring-safety-switches/
    // Uses the Bounce2 library: https://github.com/thomasfredericks/Bounce2
    //
    // When a button is pressed, the input turns HIGH.
    //
    // Normally only one 'enum' is used for the state, that controls the code.
    // This sketch has also a 'enum' for the buttons, which is called the input state.
    // define the different states for this sketch.
    // An 'enum' is like a number of #define with increasing numbers.

    // include the library code:
    #include <Bounce2.h>
    #include <LiquidCrystal.h>

    // initialize the library with the numbers of the interface pins
    LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

    // Logical states of the main state machine
    enum
    {
      CLEAR_SENSORS,
      CHECK_SENSORS,
      WAIT_FOR_BOTH_LOW,
      WAIT_FOR_BUTTON,
      ONE_PUSHED_WAIT_FOR_OTHER_BUTTON,
      FINAL_CHECK,
      LOWER_RAILS,
      CHECK_RAIL_SENSORS,
      SAFETY_WINDOW,
      RELAY_ON,
    } state;       // an 'enum' is its own type.

    // define the different input states.
    enum
    {
      BOTH_BUTTONS_LOW,      // no buttons are pressed.
      BOTH_BUTTONS_HIGH,     // both buttons are pressed.
      ONE_BUTTON_HIGH,       // probably one of the buttons is pressed.
    };

    // Define the different sensor states

    enum
    {
      BOTH_SENSORS_HIGH, // Both Sensors are not blocked
      BOTH_SENSORS_LOW, // Both Sensors are blocked
      SENSOR1_HIGH_SENSOR2_LOW,  // Sensor 1 is not blocked but Sensor 2 is
      SENSOR2_HIGH_SENSOR1_LOW,   // Sensor 2 is not blocked but Sensor 1 is
    };

    // Define the different rail sensor states

    enum
    {
      BOTH_RSENSORS_HIGH, // Both sensors are not blocked
      BOTH_RSENSORS_LOW,  // Both rail sensors are blocked
      SENSOR3_HIGH_SENSOR4_LOW,  // Sensor 3 is not blocked Sensor 4 is
      SENSOR4_HIGH_SENSOR3_LOW,  // Sensor 4 is not blocked Sensor 3 is
    };

    const int ButtonPin1 = 2;
    const int ButtonPin2 = 3;
    const int Sensor1Pin = 6;
    const int Sensor2Pin = 24;
    const int Sensor3Pin = 30;
    const int Sensor4Pin = 31;
    const int RelayPin = 5;
    const int RelayPin2 = 13;
    const int RelayPin3 = 34;
    const int IndicatorPin = 4;
    const int IndicatorPin2 = 25;
    const int IndicatorPin3 = 26;
    const int IndicatorPin4 = 27;
    const int IndicatorPin5 = 35;

    // The 'previousMillis' is exclusively for the state machine portion only.
    // It is used for different software timers in different states.
    // That is okay, because within the state machine the states are seperated from each other.
    // Funtions outside the state machine would require a separate timer.
    unsigned long previousMillis;

    const unsigned long RelayOnTime = 1750;    // Length of time for relay
    const unsigned long TimeFrameForSecondButton = 300; // Length of time to allow two pushes
    const unsigned long PushSafetyWindow = 300; // Safety Delay after push to be sure part is in place

    // Counters for the number of failed relay triggers and successful cycles.
    // They can probably be normal integers as well.
    unsigned long failed = 0;
    unsigned long success = 0;

    // Instantiate Bounce objects
    Bounce debouncer1 = Bounce();
    Bounce debouncer2 = Bounce();
    Bounce debouncer3 = Bounce();
    Bounce debouncer4 = Bounce();
    Bounce debouncer5 = Bounce();
    Bounce debouncer6 = Bounce();

    void setup()
    {
      lcd.begin(16, 2);
      lcd.print("On");
      Serial.begin(9600);
      Serial.println("Unit Online");

    // Set up first button
      pinMode(ButtonPin1, INPUT);
      debouncer1.attach(ButtonPin1);
      debouncer1.interval(15); //Debounce time

    // Set up second button
      pinMode(ButtonPin2, INPUT);
      debouncer2.attach(ButtonPin2);
      debouncer2.interval(15); //Debounce time

    // Set up Sensor1
      pinMode (Sensor1Pin, INPUT);
      debouncer3.attach(Sensor1Pin);
      debouncer3.interval(5); //Debounce time

    // Set up Sensor2
      pinMode (Sensor2Pin, INPUT);
      debouncer4.attach(Sensor2Pin);
      debouncer4.interval(5); //Debounce time

      // Set up Sensor3
      pinMode (Sensor3Pin, INPUT);
      debouncer5.attach(Sensor3Pin);
      debouncer5.interval(5); //Debounce time

    // Set up Sensor4
      pinMode (Sensor4Pin, INPUT);
      debouncer6.attach(Sensor4Pin);
      debouncer6.interval(5); //Debounce time

      pinMode(RelayPin, OUTPUT);      // OUTPUT to Relay
      pinMode(RelayPin2, OUTPUT);     // OUTPUT to Second Relay
      pinMode(RelayPin3, OUTPUT);     // OUTPUT to Third Relay
      pinMode(IndicatorPin, OUTPUT);  // OUTPUT to Indicator LED
      pinMode(IndicatorPin2, OUTPUT); // OUTPUT to Second Indicator LED
      pinMode(IndicatorPin3, OUTPUT); // OUTPUT to Third Indicator LED
      pinMode(IndicatorPin4, OUTPUT); // OUTPUT to Fourth Indicator LED
      pinMode(IndicatorPin5, OUTPUT); // OUTPUT to Fifth Indicator LED

      Serial.println("Going to CLEAR_SENSORS state");

    // Set initial state of the machine
      state = CLEAR_SENSORS;
    }

    void loop()
    {

      unsigned long currentMillis = millis();

    // Update the Bounce instances
      debouncer1.update();
      debouncer2.update();
      debouncer3.update();
      debouncer4.update();

      int inputState = getInputState();
      int sensorState = getSensorState();
      int RsensorState = getRSensorState();

    // Process the data in a state machine.
    // The output part is also in the state machine.
      switch(state)
      {
        case CLEAR_SENSORS:
           // Turn off relay2 and wait til everything is clear
            lcd.setCursor(0,0);
            lcd.print("Clear Machine");
            digitalWrite(RelayPin2, LOW);     // Turn OFF Relay 2
            digitalWrite(IndicatorPin2, LOW); // Turn OFF IndicatorPin 2
            digitalWrite(IndicatorPin4, HIGH); // Turn ON IndicatorPin 4
          if(sensorState == BOTH_SENSORS_HIGH)
          {
            // Prepare to go to the next state
            Serial.println("Machine Clear Going to CHECK_SENSORS state");
            state = CHECK_SENSORS;
          }
          break;
        case CHECK_SENSORS:
          // Turn on Relay 2 and then verify the sensor is engaged before proceeding
            lcd.setCursor(0,0);
            lcd.print("Load Barricade");
            digitalWrite(RelayPin2, HIGH);  // Turn on Relay 2
            digitalWrite(IndicatorPin2, HIGH); // Turn ON IndicatorPin 2
            digitalWrite(IndicatorPin3, HIGH); // Turn ON IndicatorPin 3
            digitalWrite(IndicatorPin4, LOW); // Turn OFF IndicatorPin 4
          if(sensorState == SENSOR2_HIGH_SENSOR1_LOW)
          {
            // Prepare to go to the next state
            Serial.println("Machine Clear Going to WAIT_FOR_BOTH_LOW state");
            state = WAIT_FOR_BOTH_LOW;
          }
          break;
        case WAIT_FOR_BOTH_LOW:
          // Both buttons must be released to be able to continue.
            lcd.setCursor(0,0);
            lcd.print("Wait For Release");
            digitalWrite(IndicatorPin3, LOW); // Turn OFF IndicatorPin 3
          if(inputState == BOTH_BUTTONS_LOW)
          {
            // Prepare to go to the next state.
            Serial.println("Going to WAIT_FOR_BUTTON state");
            state = WAIT_FOR_BUTTON;
          }
          break;
        case WAIT_FOR_BUTTON:
    // This is the state when everything is idle and no buttons are pressed.
    // Normally both buttons are released.
    // Waiting for the first button to be pressed.
    // Both buttons could be pressed at the same time !
            lcd.setCursor(0,0);
            lcd.print("Engage Buttons   ");
          if(inputState == ONE_BUTTON_HIGH || inputState == BOTH_BUTTONS_HIGH)
          {
    // At least one button is pressed.
    // Prepare to go to the next state.
    // Start a timer, because there is a timeout.
            Serial.println("Going to ONE_PUSHED_WAIT_FOR_OTHER_BUTTON state");
            previousMillis = currentMillis;
            state = ONE_PUSHED_WAIT_FOR_OTHER_BUTTON;
           }
          break;
        case ONE_PUSHED_WAIT_FOR_OTHER_BUTTON:
            lcd.setCursor(0,0);
            lcd.print("Wait for Other");
          if(inputState == BOTH_BUTTONS_LOW)
          {
    // The button was released. That's not what we want.
    // Return to the state to wait for both off.
            Serial.println("Going to WAIT_FOR_BOTH_LOW state");
            state = WAIT_FOR_BOTH_LOW;
          }
          else if(currentMillis - previousMillis >= TimeFrameForSecondButton)
          {
    // The timeout has ended.
    // The second button was not pushed after the first button
    // within the timeout. That's too bad.
            Serial.println("Too Long Going to WAIT_FOR_BOTH_LOW state");
            state = WAIT_FOR_BOTH_LOW;
          }
          else if(inputState == BOTH_BUTTONS_HIGH)
          {
    // The timeout has not ended and is still running.
    // And now both buttons are pressed.
    // We can continue.
    // Start the timer for the SAFETY_WINDOW state.
            Serial.println("Going to FINAL_CHECK state");
            previousMillis = currentMillis;
            state = FINAL_CHECK;
          }
          break;
        case FINAL_CHECK:
          if(sensorState != SENSOR2_HIGH_SENSOR1_LOW)
          // Check to make sure the barricade hasn't been removed
          {
            // Prepare to go to the next state
            Serial.println("Machine Clear Going to CHECK_SENSORS state");
            state = CHECK_SENSORS;
          }
          else if(sensorState == SENSOR2_HIGH_SENSOR1_LOW)
          {
            Serial.println("Going to LOWER_RAILS state");
            state = LOWER_RAILS;
          }
          break;
        case LOWER_RAILS:
            lcd.setCursor(0,0);
            lcd.print("Lowering Rails  ");
          if(inputState != BOTH_BUTTONS_HIGH)
          // Check to be sure safety buttons are held and if not wait for another try
          {
            Serial.println("Going to WAIT_FOR_BOTH_LOW state from LOWER_RAILS");
            state = WAIT_FOR_BOTH_LOW;
          }
          else
          // If buttons 1 and 2 are still held proceed to turn on Relay 3 and onto the sensor check
          {
            digitalWrite(RelayPin3, HIGH);  // Turn ON RelayPin3
            digitalWrite(IndicatorPin5, HIGH); // Turn ON IndicatorPin5
            Serial.println("Going to CHECK_RAIL_SENSORS state");
            state = CHECK_RAIL_SENSORS;
          }
          break;
        case CHECK_RAIL_SENSORS:
           lcd.setCursor(0,0);
           lcd.print("Checking Rails  ");
           Serial.println(RsensorState);
           // Wait until the sensors are blocked to move into the next state
          if(RsensorState == BOTH_RSENSORS_LOW)
          {
            Serial.println("Going to SAFETY_WINDOW state");
            state = SAFETY_WINDOW;
          }
          break;
        case SAFETY_WINDOW:
            lcd.setCursor(0,0);
            lcd.print("Wait a second");
          if(inputState != BOTH_BUTTONS_HIGH)
          {
    // During the safety time window, a button was released.
    // Return to idle.
            Serial.println("Going to WAIT_FOR_BOTH_LOW state");
            digitalWrite(RelayPin, LOW);  // Turn OFF RelayPin
            digitalWrite(IndicatorPin, LOW); // Turn OFF IndicatorPin
            digitalWrite(RelayPin3, LOW);  // Turn OFF RelayPin3
            digitalWrite(IndicatorPin5, LOW); // Turn OFF IndicatorPin5
            state = WAIT_FOR_BOTH_LOW;
          }
          else if(currentMillis - previousMillis >= PushSafetyWindow)
          {
    // The buttons are still pressed.
    // The time window has reached the end.
    // Prepare to go to the next state.
            Serial.println("Going to RELAY_ON state");
            previousMillis = currentMillis;
            digitalWrite(RelayPin, HIGH);  // Turn ON RelayPin
            digitalWrite(IndicatorPin, HIGH); // Turn ON IndicatorPin
            state = RELAY_ON;
          }
          break;
        case RELAY_ON:
            lcd.setCursor(0,0);
            lcd.print("Relay Engaged   ");
          if(inputState != BOTH_BUTTONS_HIGH)
          {
    // One of the buttons was released.
    // Stop the relay and return to idle.
    // Although the relay was triggered, it was not succesful.
            failed++;
            Serial.print("Failed=");
            Serial.println(failed);
            Serial.println("Going to WAIT_FOR_BOTH_LOW state");
            digitalWrite( RelayPin, LOW);  // Turn Off RelayPin
            digitalWrite(IndicatorPin, LOW); // Turn Off IndicatorPin
            digitalWrite(RelayPin3, LOW);  // Turn OFF RelayPin3
            digitalWrite(IndicatorPin5, LOW); // Turn OFF IndicatorPin5
            state = WAIT_FOR_BOTH_LOW;
          }
          else if(currentMillis - previousMillis >= RelayOnTime)
          {
            // Everyting was okay.
            // The buttons are still pressed.
            // It was complete and succesful.
            // It is time to turn off the relay and return to idle.
            success++;
            Serial.print("Success=");
            Serial.println(success);
            Serial.println("Going to CLEAR_SENSORS state");
            lcd.setCursor(0,1);
            lcd.print("Cycles ");
            lcd.print(success);
            digitalWrite(RelayPin, LOW);  // Turn Off RelayPin
            digitalWrite(IndicatorPin, LOW); // Turn Off IndicatorPin
            digitalWrite(RelayPin3, LOW);  // Turn OFF RelayPin3
            digitalWrite(IndicatorPin5, LOW); // Turn OFF IndicatorPin5
            state = CLEAR_SENSORS;
          }
          break;
        default:
            Serial.println("Error, unknown state");
          break;
        }
    }

    // This function returns the input state.
    // There is no StateChangeDetection, because a state machine is used.
      int getInputState()
    {
      int returnInputState;

    // Read the debounce state and create an input state according to the 'enum' values.
      int value1 = debouncer1.read();
      int value2 = debouncer2.read();

        if(value1 == LOW && value2 == LOW)
        {
          returnInputState = BOTH_BUTTONS_LOW;
        }
        else if(value1 == HIGH && value2 == HIGH)
        {
          returnInputState = BOTH_BUTTONS_HIGH;
        }
        else
        {
        // Not both on, not both off, so it must be something else.
        returnInputState = ONE_BUTTON_HIGH;
        }

      return(returnInputState);
    }

     // This function is to return the state of sensors 1 and 2
      int getSensorState()
    {
      int returnSensorState;

    // Read the sensor states and create an input state
      int value3 = debouncer3.read();
      int value4 = debouncer4.read();

        if(value3 == HIGH && value4 == HIGH)
        {
          returnSensorState = BOTH_SENSORS_HIGH;
        }
        else if(value3 == HIGH && value4 == LOW)
        {
          returnSensorState = SENSOR1_HIGH_SENSOR2_LOW;
        }
        else if(value4 == HIGH && value3 == LOW)
        {
          returnSensorState = SENSOR2_HIGH_SENSOR1_LOW;
        }
        else
        {
          returnSensorState = BOTH_SENSORS_LOW;
        }
      return(returnSensorState);
    }

     // This function is to return the state of Sensors 3 and 4
      int getRSensorState()
    {
      int returnRSensorState;

    // Read the sensor states and create an input state
      int value5 = debouncer5.read();
      int value6 = debouncer6.read();

      if(value5 == LOW && value6 == LOW)
        {
          returnRSensorState = BOTH_RSENSORS_LOW;
        }
        else if(value5 == HIGH && value6 == LOW)
        {
          returnRSensorState = SENSOR3_HIGH_SENSOR4_LOW;
        }
        else if(value6 == HIGH && value5 == LOW)
        {
          returnRSensorState = SENSOR4_HIGH_SENSOR3_LOW;
        }
        else
        {
          returnRSensorState = BOTH_RSENSORS_HIGH;
        }
      return(returnRSensorState);
    }

The part giving me trouble is this state:

    case CHECK_RAIL_SENSORS:
       lcd.setCursor(0,0);
       lcd.print("Checking Rails  ");
       Serial.println(RsensorState);
       // Wait until the sensors are blocked to move into the next state
      if(RsensorState == BOTH_RSENSORS_LOW)
      {
        Serial.println("Going to SAFETY_WINDOW state");
        state = SAFETY_WINDOW;
      }
      break;

It may be something to do with how the sensor state is acquired. I am using Bounce2 to debounce the inputs.

     // This function is to return the state of Sensors 3 and 4
      int getRSensorState()
    {

      int returnRSensorState;

    // Read the sensor states and create an input state
      int value5 = debouncer5.read();
      int value6 = debouncer6.read();

      if(value5 == LOW && value6 == LOW)
        {
          returnRSensorState = BOTH_RSENSORS_LOW;
        }
        else if(value5 == HIGH && value6 == LOW)
        {
          returnRSensorState = SENSOR3_HIGH_SENSOR4_LOW;
        }
        else if(value6 == HIGH && value5 == LOW)
        {
          returnRSensorState = SENSOR4_HIGH_SENSOR3_LOW;
        }
        else
        {
          returnRSensorState = BOTH_RSENSORS_HIGH;
        }
      return(returnRSensorState);
    }

Any input is greatly appreciated! Please let me know if more clarification is necessary.

*Edit 07/12/18*

IF you use this code don't forget to update this section for it to work! The complete, corrected code is too large to post:

    // Update the Bounce instances
      debouncer1.update();
      debouncer2.update();
      debouncer3.update();
      debouncer4.update();
      debouncer5.update();
      debouncer6.update();

title: State machine waiting for input state isn't getting input states for unknown reason

Answers: 1

body:
Your debouncer update section:

    // Update the Bounce instances
      debouncer1.update();
      debouncer2.update();
      debouncer3.update();
      debouncer4.update();

is missing `debouncer5.update();` and `debouncer6.update();`. It is required to call `update()` once per `loop()` to ensure the object is up to date.


body:
Im using the SparkFun MAG3110 3D sensor:
https://www.sparkfun.com/products/12670

My application is essentially to make a contactless "magnetic joystick" using a local magnet for accurate and constant 3D position sensing in x, y, x planes of a local magnet, exactly like in this video (skip to 1:06):
https://www.youtube.com/watch?v=CO6y6bjFfmY

The magnet I'm using is constant, so i'm trying to figure out a way to remove the earths magnetic field noise around the sensor so it cannot interfere with the sensors readings as if the earths magnetic field was virtually not present.

I've already written code that takes about 50 samples in each plane (x,y,z) and takes the average of each of the planes and outputs those readings minus the average offset values (Ex: Serial.print(x-xavg), Serial.print(y-yavg), Serial.print(z-zavg)). I did this to basically "zero out" the earths magnetic field, like zeroing a weight scale.

That wasn't really effective and results were not anywhere near constant after introducing and removing the local magnet, over and over again.

I've considered:

- a low pass filter
- sensor fusion using my gyroscope/accelerometer module
(I know that sensor fusion is usually used to calibrate the Magnometer to be a more accurate compass, but is there anyway to use this technique to  eliminate the earths magnetic field?)
- using data from http://www.magnetic-declination.com/ to tie into my calculations to offset the readings
- Using an electromagnet module to output the earths magnetic field inverted continuously in an attempt to cancel out the earths magnetic field
- trying to find a whole new sensor completely that does not have a low enough sensitivity to even detect earths magnetic field

So my questions are:

1. Is there any way to do this?
2. Are any of my considerations practical or possible?

3. Are there even any 3d magnetic sensors on the market that do NOT pick up the earths magnetic field? - I've contacted SparkFun, Arrow, ST, and other companies about this exact question and never really get a sure answer on this question specifically?

4. if not, how was this man in the video able to reduce noise around his sensor? - He shows visually that his sensor is starting to filter out noise, saying that he's using an "adaptive averages" algorithm and links to some code, but I was unable to see/find that and don't understand how he is doing that?

title: How to filter or eliminate earths magnetic field readings around 3D Magnetic sensor?

Answers: 3

body: One option is a magnetic gradiometer.  This consists of two magnetometers, which are placed at different distances from the local magnet (one close, one far).  You subtract the readings to eliminate dependence on the earth's magnetic field, on the (fairly good) assumption that the earth's field does not change over the distance between the sensors.

body:
If you're already subtracting the mean of several samples of the ambient field, what's left should be noise, and much lower than your signal (the field due to your handheld magnet).

If you're trying to get a level of precision at the same order of magnitude as the noise, you'll need a larger 'N' (sample size), perhaps of both the ambient and of the desired signal, or apply even more stringent statistical techniques.

But I doubt that's what the experimenter in the video was doing. It's more likely he was close enough the sensor and with a strong enough magnet, that the noise was insignificant by comparison. He was using a rare-earth magnet - are you? Those typically have a stronger field that a more common ceramic or steel one. If not, you may need to use yours at a smaller distance from the sensor to get a similar signal to noise ratio.

body:
Earth magnetic field is pretty constant. In your measurements it will show up as an offset that you could subtract, but of course it will change if the sensor rotates.

Whatever measurement noise you see certainly doesnt' come from Earth. Either your setup is close to a local source of magnetic radiation (inductors, wires with high alternating current), or your sensor picks up noise from its power supply. Put your sensor away from high currents, power it with batteries and see how much noise you'll get in that case.


body:
I'm using this tutorial from Sparkfun
https://learn.sparkfun.com/tutorials/load-cell-amplifier-hx711-breakout-hookup-guide

And using THEIR code. The only difference is I added a delay so it wouldn't write a reading 10x a second.

**QUESTION:**
**How do I get nonzeros?**

    #include "HX711.h"
    #define DOUT  3
    #define CLK  2
    HX711 scale(DOUT, CLK);
    float calibration_factor = -7050; //-7050 worked for my 440lb max scale setup
    void setup() {
      Serial.begin(9600);
      Serial.println("HX711 calibration sketch");
      Serial.println("Remove all weight from scale");
      Serial.println("After readings begin, place known weight on scale");
      Serial.println("Press + or a to increase calibration factor");
      Serial.println("Press - or z to decrease calibration factor");
      scale.set_scale();
      scale.tare(); //Reset the scale to 0
      long zero_factor = scale.read_average(); //Get a baseline reading
      Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
      Serial.println(zero_factor);
    }
    void loop() {
      scale.set_scale(calibration_factor); //Adjust to this calibration factor
      Serial.print("Reading: ");
      Serial.print(scale.get_units(), 20);
      Serial.print(" lbs"); //Change this to kg and re-adjust the calibration factor if you follow SI units like a sane person
      Serial.print(" calibration_factor: ");
      Serial.print(calibration_factor);
      Serial.println();
      if(Serial.available())
      {
        char temp = Serial.read();
        if(temp == '+' || temp == 'a')
          calibration_factor += 10;
        else if(temp == '-' || temp == 'z')
          calibration_factor -= 10;
      }
      delay(2000);
    }

NOTE: I did not yet solder anything because I don't want to mess up the soldering and have to buy new cells and wait a week for shipping. So I placed pinheads in the amplifier and connected with m/f jumpers, and used alligator clips to connect to the loose wires.

[![load cell between 2 boards, as instructed][2]][2]
[![hookup 1][3]][3]
[![hookup 2][4]][4]
[![readout][5]][5]

  [2]: https://i.stack.imgur.com/WvyHx.jpg
  [3]: https://i.stack.imgur.com/XD7jz.jpg
  [4]: https://i.stack.imgur.com/mBkUY.jpg
  [5]: https://i.stack.imgur.com/xX7Jz.png

title: hx711 and load cell read out 0 for calibration

Answers: 1

body:
Only VCC was connected to 5v. Had to add a breadboard to connect VDD as well.

(The kind folks at Sparkfun were able to help me out)


body:
I'm trying to use my button as a switch (the led goes on after I push the button and the led goes off when I push the button again). I know I have the right circuit, because I also used a code from the internet, which looks really like mine. But my code doesn't work. The led doesn't go on. Does anyone know what is wrong with my code?

I have found the mistake now. The last 2 lines of the code were in the if statement block. But why doesn't it work then?

Here is the code i have written:

    int ledPin = 8;
    int buttonPin = 4;

    int ledState = HIGH;      // the current state of the LED
    int previousState = LOW;  // the previous state of the button
    int readingState ;        // the current state of the button

    void setup() {
       // put your setup code here, to run once:
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT);
    }

    void loop() {
      // put your main code here, to run repeatedly:
    readingState = digitalRead(buttonPin);

    if(readingState == HIGH && previousState == LOW){
      if (ledState == HIGH){
        ledState = LOW;
      }

      else{
        ledState = HIGH;
        }

    digitalWrite(ledPin, ledState);
    previousState = readingState;

    }
    }

title: Button Switch arduino

Answers: 1

body:
> I have found the mistake now. The last 2 lines of the code were in the if statement block. But why doesn't it work then?

previousState is set to high, and is never set again, so your if statement will never execute again because previousState is always set to high.

Moving the last line out of the if block sets previousState at every loop, and can then have a value other than HIGH, and then your if condition can be satisfied.

The penultimate line could stay in the if, or be lifted out, logically it shouldn't matter.


body:
I am developing a product. I developed every module in the firmware individually. Now I am integrating them but getting memory issues. I am not able to see how the memory is allocated inside the MCU during the runtime.

Can Linux help me debug issues better, using its command than Windows platform?

Thanks in advance.

title: Which platform is better to debug Arduino memory problems? Linux or Windows?

Answers: 1

body: The operating system is irrelevant. If you want to debug the target you need a debugger and a debugging environment. That means a proper hardware debugger interface, not an Arduino's USB serial port, and a proper IDE like Atmel Studio not the Arduino IDE.  All are available for both Linux and Windows.


body:
This code seems to function, but only works once before I need to press the reset button. Otherwise, it repeats the same error message. It might have something to do with emptying the String variable.

    // A program that will allow a user to turn ON one of several LED's
    // using if...else statements.

    String pinAsk="Please select which pin you would like to supply power to:";

    // A different coloured LED will be attached to each pin number.
    int Red=14; // This one would be the A0 Header on the Arduino
    int Yellow=15; // A1
    int Green=16; // A2
    int Blue=17; // A3
    int Purple=18; // A4
    int Violet=19; // A5

    int invalidColorRed;
    int invalidColorYellow;
    int invalidColorGreen;
    int invalidColorBlue;
    int invalidColorPurple;
    int invalidColorViolet;
    // If the user didn't select any of these colours, then all these variables will
    // be given a 1. This triggers an if...else condition that prints out a message,
    // to say that they didn't enter a valid input.

    String inputColor;
     // The String variable can store integers as well as other characters

    String activePin1="The ";
    // The users input is printed out between these.
    String activePin2=" LED is now active";

    int Volts=102; // The 102 tells the Arduino to output 2+ (Two volts)

    void setup() {
     Serial.begin(9600);
     Serial.println("Colour Selection");
     Serial.println("");

     pinMode(Red,OUTPUT);
     pinMode(Yellow,OUTPUT);
     pinMode(Green,OUTPUT);
     pinMode(Blue,OUTPUT);
     pinMode(Purple,OUTPUT);
     pinMode(Violet,OUTPUT);
    }

    void loop() {
     Serial.println(pinAsk);
     Serial.println("Red = A0 (14)");
    // These describe the available pins and their colors.
     Serial.println("Yellow = A1 (15)");
     Serial.println("Green = A2 (16)");
     Serial.println("Blue = A3 (17)");
     Serial.println("Purple = A4 (18)");
     Serial.println("Violet = A5 (19)");

      while (Serial.available()==0) { } // Wait for user to respond

     inputColor=Serial.readString(); // Store their input into an empty variable

    // The following segment checks whether the user has selected to turn ON
    // the Red LED.

     if (inputColor=="14") analogWrite(Red,Volts);
     // The String variable can also store integers as well as other characters
     else if (inputColor=="A0") { analogWrite(Red,Volts); }
     else if (inputColor=="Red") { analogWrite(Red,Volts); }
     else if (inputColor=="red") { analogWrite(Red,Volts); }
    // User may only use lower-case letters.
      // The "equal equal" sign == doesn't assign a new value.
      // It will test whether a number or string is the same
    // as described at the end of the equal's sign.

     else { analogWrite(Red,LOW); }
    // If the users input, stored within inputColor, isn’t "14", "A0", "Red",
    // or "red" then this Red LED will be turned off.

     if (inputColor!="14" && inputColor!="A0" && inputColor!="Red" && inputColor!="red") { invalidColorRed=1; }

    // The exclamation mark or bang ! is a NOT operator.
    // A "bang equal" sign != is placed after a variable, such as inputPin!=
    // to say that the value must NOT be equal to "14". If the expression is true
    // (The condition is fulfilled), then a 1 is given to invalidColorRed.

    // The AND operator, shown as a double ampersand && combines
    // all the conditions into the same expression. By putting this operator `
    // between them, it tells the Arduino that all the variables must NOT be
    // any of the values described.

    // Each colour has its own invalidColor variable.
    // If the user does not enter any of the valid inputs
    // (Which means the LED is off), a 1 will be assigned to this colors
    // invalidColor variable.

    // If all these invalidColor variables have a value of 1, it means all
    // the LED’s are off. This can be made into another condition that causes
    // the Arduino to read an expression that tells the user that they haven’t
    // entered a proper input and to try again.

    // Checking to see if the user has opted to turn on the Yellow LED.
     if (inputColor=="15") analogWrite(Yellow,Volts);
     else if (inputColor=="A1" || "Yellow" || "yellow") { analogWrite(Yellow,Volts); }
    // The OR || operator combines the Lower-case and Upper-case letters in
    // the same expression. A space between the operator and variables is not
    // necessary, but improves readability. Also, a single pair of quotation
    // marks "" can encase the conditions if || is being used.
     else { analogWrite(Yellow,LOW); }

     if (inputColor!="15" && inputColor!="A1" && inputColor!="Yellow" && inputColor!="yellow") { invalidColorYellow=1; }

    // Checking to see if the user has opted to turn on the Green LED.
     if (inputColor=="16") analogWrite(Green,Volts);
     else if (inputColor=="A2") { analogWrite(Green,Volts); }
     else if (inputColor=="Green") { analogWrite(Green,Volts); }
     else if (inputColor=="green") { analogWrite(Green,Volts); }
     else { analogWrite(Green,LOW); }

     if (inputColor!="16" && inputColor!="A2" && inputColor!="Green" && inputColor!="green") { invalidColorGreen=1; }

    // Checking to see if the user has opted to turn on the Blue LED.
     if (inputColor=="17") analogWrite(Blue,Volts);
     else if (inputColor=="A3") { analogWrite(Blue,Volts); }
     else if (inputColor=="Blue") { analogWrite(Blue,Volts); }
     else if (inputColor=="blue") { analogWrite(Blue,Volts); }
     else { analogWrite(Blue,LOW); }

     if (inputColor!="17" && inputColor!="A2" && inputColor!="Blue" && inputColor!="blue") { invalidColorBlue=1; }

    // Checking to see if the user has opted to turn on the Purple LED.
     if (inputColor=="18") analogWrite(Purple,Volts);
     else if (inputColor=="A4") { analogWrite(Purple,Volts); }
     else if (inputColor=="Purple") { analogWrite(Purple,Volts); }
     else if (inputColor=="purple") { analogWrite(Purple,Volts); }
     else { analogWrite(Purple,LOW); }

     if (inputColor!="18" && inputColor!="A4" && inputColor!="Purple" && inputColor!="purple") { invalidColorPurple=1; }

    // Checking to see if the user has opted to turn on the Violet LED.
     if (inputColor=="19") analogWrite(Violet,Volts);
     else if (inputColor=="A5") { analogWrite(Violet,Volts); }
     else if (inputColor=="Violet") { analogWrite(Violet,Volts); }
     else if (inputColor=="violet") { analogWrite(Violet,Volts); }
     else { analogWrite(Violet,LOW); }

     if (inputColor!="19" && inputColor!="A5" && inputColor!="Violet" && inputColor!="violet") { invalidColorViolet=1; }

     if (invalidColorRed==1 && invalidColorYellow==1 && invalidColorGreen==1 && invalidColorBlue==1 && invalidColorViolet==1)
     {
      // This if statement is asking "Are all invalidPin variables equal to 1?"
      // In other words, "Are all the LED's off?"
      Serial.println("");
      Serial.println("That is not a valid option, please try again");
      Serial.println(""); }
      else if (invalidColorRed==0 || invalidColorYellow==0 || invalidColorGreen==0 || invalidColorBlue==0 || invalidColorViolet==0)
      {
      // If the user entered a valid input for at least one LED,
      // this message will play instead.
      Serial.println("");
      Serial.print(activePin1);
      Serial.print(inputColor); // The users input is printed out here.
      Serial.println(activePin2);
      Serial.println(""); }

      inputColor=""; // Shouldn't this empty the variable?
    }

Can someone tell me whats wrong?

title: Variable that holds the users input doesn't empty itself, so the program only works once

Answers: 1

body:
Without looking deeply into your code, this is wrong:

    if (inputColor=="A1" || "Yellow" || "yellow")

You need to repeat what you are testing against, ie.

    if (inputColor=="A1" || inputColor=="Yellow" || inputColor=="yellow")

You might want to use the auto-format tool (Ctrl+T). Putting a lot of stuff in one line is just confusing.