text:
Replacing large lookup table with switch statement
My arduino needs to take a 14-bit number and convert it to a 10-bit number. Can't use a formula for it since the data is quite random. So I created a lookup table with 2^14 elements, each containing a 10-bit value. But it's too big to fit on the arduino. So I thought of using a switch statement instead. Would this result in a significant speed decrease?
Say, for example, that the input value is 16383. How much longer would it take for the arduino to iterate through the 16384 cases compared to accessing index #16383 of an array?
EDIT: This code compiles fine and reports a program memory usage of 1000 bytes.
int xval;
int yval;

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  xval = random(0,16383);
  switch (xval) {
  case 0:
  yval = 0;
  break;
  case 1:
  yval = 4;
  break;
  case 2:
  yval = 4;
  break;
  case 3:
  yval = -60;
  ...
  case 16383:
  yval = 1023;
  break;
}
}

However, I haven't tried if it really works so maybe the compiler is optimizing away too much.
EDIT 2: Added the line Serial.println(yval); so that I'm actually doing something with yval as Majenko commented. And now it doesn't compile :'( :'( :'(
So, I'll tackle my problem in some other way.

If you don't have room for an array, what makes you think you'll be able to store the same (or more) data in the same space?

So, if you don't have some kind of formula or algorithm, did you really written 16384 numbers by hand? Normally there is some kind of algorithm, that can also be implemented in the Arduino

Haha no I didn't write them by hand but I've collected the data through an automated process.

You say you cannot use a formular. So that means random in and random out? Ok no that case you simply could short the size. If not, you should be able to use a formular. Otherwise it does not make any sense at all. Could you explain more what exactly to try to achieve? What are those 14-bit numbers and how do they relate to the 10-bit output?

You could store this table in some form of external storage. Something like EEPROM or an SD card.

214 is 16384 entries. Each entry takes 2 bytes. That's 32768 bytes. That's all the flash the ATMega328P has.
The most efficient storage will be an array in flash, and that will take 100% of it. Using a switch will take more space.
So in short: no. Just no. It won't work whatever you try. You need to come up with a radically different storage solution (external flash memory?) or use a larger chip.

As a side note, with "bit packing" you could reduce the storage to 20480 bytes, but doing a lookup of the data within that packed data (4 10-bit entries taking 5 bytes) will be slow to do since you have to work out exactly what combination of bits and bytes you need to reconstruct your 10-bit value.

I might be able to compress the array in some way. There's a lot of duplicates in the array so the amount of unique values is a lot less than 16384.

What is it you're doing that needs such a huge lookup table?

In short, an adapter that reverses some value conversion that takes place in a software.

How come Arduino compiles the code fine? I tested with the long switch statement of 16384 cases and it says it uses only 1000 bytes. I'll edit my question to include this.

If you're not actually doing anything with yval the compiler will optimise all that code out.

Dammit, you're absolutely right! :'(

Could always change to a 1284P based board, with 128K flash, will easily hold a large lookup table in PROGMEM.

Almost certainly not
Compilers often optimise switch statements using jump tables. However the entries in the jump table basically make up a lookup table with 214 entries! So you don't gain anything.
Some ideas for compression

You can use bit packing

If your numbers aren't 8 bits in size, you can pack them together. For example, if you have managed to code things in 6 byte chunks, you can squash 4 of these chunks into 3 bytes, to shrink a table by 25% (at the expense of some bit shifts when retrieving entries.)

Take advantage of frequency of duplicates

You say you have duplicates. But how many "very common" duplicates are there?
If, say, 90% of your values come from a group of 15 possible values, then you can pack 2 entries per byte, each one represented by a value from 0-14. If one of the entries is 15, then that that value is an "exception" and is looked up by binary search in a second table.
This would result in a table of size 8KB plus the size of the other table (say 4KB when you pack the 14 bit index and 10 bit value into 3 bytes.)
If you instead have a set of 254 possible "common" values, then your main table would be more like 16KB. That might be doable.

Is there any relation between input and output?

Maybe there is no formula, but there might be properties of the input that affect the properties of the output. (For example, maybe most input values 0-1024 have an output that is similar plus or minus 30.)

Write a program to find patterns in your data

Don't just use your eyes. Write a script (Python?) to count the frequency of each output value, or compare inputs to outputs, or evaluate your suspicions about the data. Graph input vs output.


text:
Arduino MySQL Connector Issues with Select only
first question i am doing so hope this is the right place.
I have an issue with an Arduino Uno and an Arduino ESP8266WiFi Shiald by WangTongze using this tutorial (https://www.instructables.com/id/ESP8266-ESP-12E-UART-Wireless-WIFI-Shield-TTL-Conv/) I have been able to connect to the my Wifi and host a small webserver.
Then with the Examples of the MySql Connector Library I have been able to do a simple Insert to a MySQL Database on a NAS Server. However, I want to be able to select a value from my DB and print it on the screen for some reason the Cursor always returns a null. I have been able to select from my PC using the same user. and created the user francis@% so that the host isn't an issue. Please note that this same code with a few tweaks worked to insert a record to the same table. Is there anything I am missing? Below is the code:
//#include <WiFi.h> // Use this for WiFi instead of Ethernet.h
#include <WiFiEsp.h> //use for ESP8266
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Emulate Serial1 on pins 2/3 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(2, 3); // RX, TX
#endif

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192,168,x,x); // IP of the MySQL server here
char user[] = "francis";
char password[] = "xxxxxx";

// WiFi card example
char ssid[] = "PintoLoco"; // your network SSID (name)
char pass[] = "xxxxxxxx"; // your network password

//WiFiClient client; // Use this for WiFi instead of EthernetClient
WiFiEspClient client; //Use this for ESP8266
MySQL_Connection conn((Client *)&client);
MySQL_Cursor cur = MySQL_Cursor(&conn);

char query[] = "SELECT Value FROM Peceras.Parameters ";

void setup() {

  Serial.println("Starting....");
  Serial.begin(115200);
  // initialize ESP module
  WiFi.init(&Serial);
  Serial.println("Connecting to WiFi");

  // Begin WiFi section
  int status = WiFi.begin(ssid, pass);
  while(status != WL_CONNECTED){
      status = WiFi.begin(ssid, pass);
    }
  // print out info about the connection:

  Serial.println("Connected to network");
  IPAddress ip = WiFi.localIP();
  Serial.print("My IP address is: ");
  Serial.println(ip);

  // End WiFi section

  Serial.println("Connecting...");
  if (conn.connect(server_addr,3306,user,password)) {
  delay(1000);
  }
  else
  Serial.println("Connection failed.");
}
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
void loop() {
  row_values *row = NULL;
  long head_count = NULL;
column_names *cols = cur_mem->get_columns();
cur_mem->execute(query);
  // Execute the query
  do {
    row = cur_mem->get_next_row();
    if (row != NULL) {
      for (int f = 0; f < cols->num_fields; f++) {
        head_count = atoi(row->values[f]);
          Serial.print("Ingestelde Temperatuur:  ");
          Serial.println(head_count);
        if (f < cols->num_fields-1) {
          Serial.println(',');

        }
      }
      Serial.println();
    }
  } while (row != NULL);
  // Deleting the cursor also frees up memory used
  delete cur_mem;
  delay(2000);
}

I do not know much about MySQL databases and absolute nothing about the Client you use on your Arduino. So my hints are only wild guesses ;-): You did not end the SQL statement with a semicolon.  Normally that's not a problem because the client lib does it for you, but this client could be an exception. You define a cursor cur you never use. Perhaps the client lib can only handle one active cursor. You select only one field "Value" but iterate over a list of fields. This is not a problem if the field "Value" exists. Perhaps you could try: "SELECT * FROM Peceras.Parameters;"

Thanks Peter, for your response, I have tried your seggestions and I get the same output sadly. The database is just one table with 3 columns and Value is one. I am unsure and thinking it might be to slow to obtain the data when doing the command? out of ideas

Sorry I did not realize that you used the Serial interface for the normal Serial to USB comunication and also for the  connection to the WIFI shield. That will not work. The program defines a Serial1  that you can use to connect to the Shield, but you have to connect the TX and RX pins of the shield with the pins D2 and D3 of the Arduino with wires. (It's been described in the instructables you linked to) I added an answer, For me  it's easier to write code than to write text. ;-) I also did not realize that you close the cursor in the for loop again and again, but you opened it just once.

I have no access to a compiler, so there might be errors.
#include <WiFiEsp.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(2, 3); // RX, TX
#endif

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192,168,x,x);
char user[] = "francis";
char password[] = "xxxxxx";

char ssid[] = "PintoLoco";
char pass[] = "xxxxxxxx";

WiFiEspClient client;
MySQL_Connection conn( (Client *) &client );
MySQL_Cursor *cur_mem = null;

// PPK: some database systems are case sensitive
// so Peceras.Parameters is not the same as peceras.parameters
// check if the tables and fields are named correctly.
char query[] = "SELECT Value FROM Peceras.Parameters";

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

  Serial.println( "Connecting to WiFi" );
  WiFi.init( &Serial1 );
  int status = WiFi.begin( ssid, pass );
  while( status != WL_CONNECTED )
  {
    status = WiFi.begin(ssid, pass);
  }

  Serial.println( "Connected to network" );
  IPAddress ip = WiFi.localIP();
  Serial.print( "My IP address is: " );
  Serial.println( ip );

  Serial.println( "Connecting DB ..." );
  if ( conn.connect( server_addr, 3306, user, password ) )
  {
    Serial.println( "DB connected." );
    cur_mem = new MySQL_Cursor( &conn );
    row_values *row = NULL;
    long head_count = NULL;
    column_names *cols = cur_mem->get_columns();

    cur_mem->execute(query);

    do
    {
      row = cur_mem->get_next_row();
      if ( row != NULL )
      {
        for ( int f = 0; f < cols->num_fields; f++ )
        {
          head_count = atoi( row->values[f] );
          Serial.print( "Ingestelde Temperatuur:  ");
          Serial.println( head_count );
          if ( f < cols->num_fields - 1 )
          {
            Serial.println(',');
          }
        }
        Serial.println();
      }
    } while (row != NULL);

    // Deleting the cursor also frees up memory used
    // PPK: I'm not sure if this is a good idea, I don't know
    delete cur_mem;
  }
  else
  {
    Serial.println( "DB Connection failed." );
  }
}

void loop()
{
  // PPK: I would recommend to do the select in the setup section
  // It looks like you want to run it just once
}

Edit
Please note, that this code only works if you connect the software serial pins D2, D3 to the respective RX and TX pins on the Shield. You have to bend the pins (P0-P3) of the shield to disconnect them from the Arduino. Then you have to connect D2 and D3 to P0 and P1. This is described in step 1 of the instructables you linked to in the question. See the picture at the end of Step 1. https://www.instructables.com/id/ESP8266-ESP-12E-UART-Wireless-WIFI-Shield-TTL-Conv/

Thanks Peter for the response, i tried this code, and now it doesn't start the Esp Module, I get a timeout: [WiFiEsp] >>> TIMEOUT >>>
[WiFiEsp] Cannot initialize ESP module

source: Stack Exchange

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

sort: votes


text:
How do I run a function every 10th time through a loop?
I currently have a function that poles all my sensors every time through it's loop, but I want to pole one of the sensors only every 10th time.  Currently there is a 10 millisecond delay at the beginning of my function.  I know I could increment a counter and use modulo, but is there a better practice for this?

Please show us the sketch you're using.

It's a thousand line program half of which is dedicated to poling the various sensors.  I just need the general solutions to doing something once for every 10 times you do something else.

You've already hit the nail on the head with the modulo.  Or there's good old count up until the variable hits 10 and set it back to zero.  Aside from that it's going to be pretty situation specific.

modulo it is then, thanks

the word is poll, not pole

decrement a counter ... if it reaches zero, then poll the sensor and reload the counter ... the microcontroller has an efficient way of checking for zero values by way of the zero flag that is set by the decrement instruction

for(int i=0; i < 9999; ++i)
{
    if(i % 10 == 0)
    {
         //my actions on i = 0, 10, 20, 30 ...
    }
}

Normally it's suboptimal to reduce the speed of loop just to be able to count them.
Apply the BlinkWithoutDelay principle instead (which is not about Blink, but about WithoutDelay)

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


text:
Is there a way to make a function take an exact number of clock cycles?
Is it possible to use something like a compiler directive to pad a function with do nothing instructions so that as you add lines of code or take them away it always executes in the same amount of time?  I know there is the blink without delay style of writing a loop, but I want something a little more exact.

Please take the [tour] and read "[ask]", then come back and provide some more bits of information, at least which compiler on which system you are using. Some background why you need this would be nice, too. Oh, and please [edit] your question, don't add comments, this is not a forum. -- I don't know of any compiler that has such an option; and I know several quite different compilers. Most probably you will need to code this on assembly level by hand.

In avr-gcc you can add a single clock cycle by asm volatile ("nop"); But you cannot measure by code, how many clock cycles the controller already spent in some other ISR.

For me that sound like you are trying to shoot sparrows with canons. Why do you need the function to always execute in the same amount of time while still changing it's code? There are other exact methods to trigger the regular execution of a function (via Timers).

you could just take a time snapshot up top, and another one when your code is done, then delay or while before returning, until the duration is acceptable.

(offtopic, sorry) Sorry for the deletion of your this post. I suggest to re-ask it, but make it more clear, what you want to do. I believe you want to convert your laptop to an external SATA hard drive (possibly to an external USB), which is a very interesting problem. Funny thing is that you could actually still use your laptop, until you do not mount a single partition multiple times.

@peterh IDK which stack exchange to ask on

To the best of my knowledge, there is not. What you speak of is possible, but it must be done manually by counting cycles, and I suspect it wouldn't actually help you. (And then you get into CISC issues where instructions can take different amounts of time to execute, potentially depending on arguments. Arduino (the actual one) is kinda safe from that, but branch instructions still take multiple cycles, for instance. This says nothing about all the boards that work with, but aren't, Arduinos.)
There are two potential routes for this.

If this is for crypto, where you want to avoid side-channel attacks by detecting the length of an authentication or hashing function, it's not a good idea. Use a well-known library to do it instead, since in practicality it's not a good or safe idea to write your own (although if it's for a homemade door lock or safe lock, it's probably not a relevant issue since there are larger and more important security issues that will likely be found first despite your best efforts).
If, as I suspect, you simply want a piece of code to run at very precise time intervals, I suggest you look up something like the FreeRTOS port for Arduino. That will let you schedule a task to run preemptively so that it will always run at intervals. The BWOD sketch is still quite accurate, mind you, and below is a self-correcting version that compensates for any times that it might run a bit late (meaning that it should ALWAYS execute with millisecond precision, repeatably):

  unsigned long currentMillis = millis();//and you could always use micros()

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis += interval;//adjustment for additional accuracy

    //The task you want to run would go below:
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }

The caveat to your stated goal is that any microprocessor WILL NOT execute code exactly when you want. Arduino too is incapable of this, since even a blank sketch runs several interrupts that will take over the processor for short periods of time, causing your hypothetical sketch to be delayed. You HAVE to use a reference method like BWOD or a scheduler like FreeRTOS. These use a reference or set up their own interrupt to make sure that they run on time, with the only interrupts that could be an issue being the ones that run during that instance of the task.
What this means is that they have a bit of overhead to add spacing between tasks so that if one is delayed, it won't cause the next to run late. So do mind that you'll lose a quite small percentage of CPU time to your scheduler, but if that's really an issue, find a better board (like TI TIVA/Energia IDE).

You can use a timer with prescaler set to 1 in combination with a counter module. Attach interrupts to the compare and the overflow events. In the corresponding ISRs you handle the counting...
I have no example for you and it might be a bit tricky how to implement the ISRs, but it's possible for sure, as long as you count a reasonable amount of clock cycles (firing an interrupt each cycle e.g. will not work as the calculations in the ISR take some time).


text:
Uploading a sketch without using the usb cable
I've lost my usb cable used to upload a Sketch to my arduino from my laptop. I do have my Bluetooth 4.0 module. Can I use it to upload my sketches?

What bluetooth module is is exactly?

You can use the ICSP pins, but you can't drive those with Bluetooth. https://www.arduino.cc/en/tutorial/arduinoISP

In your case, it would be easier to buy a new cable. But you asked a very interesting question in general. I'll have to think about it. Some thoughts: If you did not connect the USB to Serial part of the Arduino, you should be able to connect the RX and TX pins of the Arduino to the Bluetooth module (if the module is connectable to an UART see @chrisl s comment) ). Then you need a driver on the Laptop that simulates the Bluethooth connection to the Module as a COMx port (like to USB to SERIAL driver does). Possibly you need access to the reset pin also.

Specifically I asked about the module, because every bluetooth slave device will give the master specific endpoint types (could be audio, HID or Serial interface for example). Devices like HC-06 and HC-05 will present Serial interface endpoints. The OS of the PC should then handle the bluetooth device accordingly and create a virtual com/serial port for it, that you can use. But we currently cannot know, if your bluetooth module does this.

I think @chrisl explained it well.  In case you did not understand, inside Bluetooth, like inside USB, there exists many protocols that people do not think about as the computers "just take care of it".  You would need to use the Bluetooth serial port protocol on your computer and have on hand some sort of Bluetooth adapter hardware that supports the Bluetooth serial protocol complete with serial port wires that are logic level compatible with the particular Arduino processor you are using.  However, after thinking about all that, clearly, it would be much easier to purchase a new USB cable.


text:
Can't use millis() instead of delay
I am making a home coming/leaving light for car. First I want that whenever I press the car key lock, a timer will start for 10 seconds. And if I press a button twice within 10 seconds, pin 13 will remain high for 10 seconds. If I don't press the button it returns to the void loop or condition may get false. I am working on it but I'm not getting the correct approach. I'm not able to use millis twice in this program.
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;
unsigned long previousMillis = 0;
const long interval = 5000;

void setup() {
  Serial.begin(9600);
  pinMode(8, INPUT_PULLUP);
  pinMode(13, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  buttonState = digitalRead(8);
  if (buttonState != lastButtonState) {
    if (buttonPushCounter <= 2) {
      if (buttonState == LOW) {
        buttonPushCounter++;
        Serial.println("on");
        Serial.print("number of button pushes: ");
        Serial.println(buttonPushCounter);
        if (buttonPushCounter % 3 == 0) {
          if (currentMillis - previousMillis > 10000) {
            digitalWrite(13, HIGH);
            previousMillis = currentMillis;
          } else {
            digitalWrite(13, LOW);
          }
        } else {
          digitalWrite(13, LOW);
        }
      } else {
        digitalWrite(13, LOW);
      }
    } else {
      buttonPushCounter = 0;
    }
    lastButtonState = buttonState;
  }
}

You are not using millis() at all in this program. You call it once at save the time stamp into a variable that you don't use afterwards.

I have edited the program as you said.

Please edit your program to get compileable code (Right now the braces don't match)
And please match your code to your description. You talk about 10s several times but in the code you use 5s

thanx for improving the code.but the led doesnt go off after 10 seconds.

Here is what you have asked for:

I am making home coming/leaving light for car. First i want that
  whenver i press car key lock a timer will start for 10 second.And if i
  press button twice within 10 second pin 13 will high remain for 10
  second and if i cant press the button it return to the void loop aor
  condition may get false. I am working on it but dont getting the
  correct approach . But i am not able to use millis twicely in this
  program.

So, I have refactored, and done my best to interpret your words, and the code that you wrote.
You will see that I broke down quite a bit the deep nesting of your code into separate methods.  I hope that you see that it makes it more readable and understandable.
I have replaced the "magic numbers" like 10000 with more readable code like tenSeconds.  And I hope the code does what you want now, but I'm not sure.  Hopefully the readability has improved enough that you can massage and reshape the code into what you want it to do, as well as shown you what direction to head when you don't understand your own code because it has grown (deeper, longer, more complicated, etc.) as most code does.
In the professional coding world, allowing code to remain like that is called "not paying down your design debt" and you (or your organization) will pay the consequences, with interest, just like a credit card.
Finally, note that my comments don't restate the code, but tries to add something (mine often tries to finish sentences involving readable code).  My comments also tend to be on the ends of lines to try to stay out of the way.
This code compiles, but has not been tested on an actual Arduino.  Please let me know if this meets your need, and please choose this as the answer if it does answer your question, and at least please vote up the answer if it doesn't quite answer you...   ...and give me a second chance, if possible.  Thanks.
// pins defined and named
int pin_button = 8;         // button Pin
int pin_LED = 13;           // LED Pin

int currentButtonState = 0;         // current state of the button
int lastButtonState = 0;

int buttonPushCounter = 0;   // counter for the number of button presses
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
const unsigned int tenSeconds = 10000; // 10,000 milliseconds

void setup()
{
    pinMode(pin_button, INPUT_PULLUP);
    pinMode(pin_LED, OUTPUT);
}

void loop()
{
    currentMillis = GetCurrentMillis();
    if (ButtonIsToggled() == 1)
    {
        CountButtonPushes();
    }
}

int ButtonIsToggled()
{
    int isToggled = 0;
    currentButtonState = digitalRead(pin_button);
    if (currentButtonState != lastButtonState)
    {
        lastButtonState = currentButtonState;
        isToggled = 1;
    }
    return isToggled;
}

void CountButtonPushes()
{
    int valueToWrite = LOW; // LED-OFF is default value unless overridden

    if (currentButtonState == LOW) // we just toggled from HIGH to LOW...
    {
        buttonPushCounter++; // We've successfully completed another button-press
        if (buttonPushCounter % 3 == 0) // if (buttonPushCounter==3) should be faster
        {                               // because compare is faster than division
            buttonPushCounter = 0;  // Reset
            valueToWrite = HIGH; // LED-ON
        }
    }

    if (valueToWrite == HIGH) // LED is ON
    {
        digitalWrite(pin_LED, HIGH); // valueToWrite
        while (currentMillis - previousMillis < tenSeconds)
        {
            // do nothing -- wait while LED is on
            // busy wait. Consider sleeping instead.
            currentMillis = GetCurrentMillis();
        }
        previousMillis = currentMillis;
        digitalWrite(pin_LED, LOW);
    }
}

unsigned long GetCurrentMillis()
{
    return millis();
}


text:
Can someone help me decipher the code for the arduino? I am totally lost
The code is as follows:
void loop(){

    light = analogRead(5);
    Serial.println(light);
    analogWrite(3,light/4);

}

Not really a physics question, but I will answer anyway.
loop() is the standard Arduino function which contains code that the microprocessor runs repeatedly (as opposed to code in setup() which is only run once).
light = analogRead(5); takes an analogue voltage reading from pin 5, encodes it as an integer value (either 10 or 12 bits depending on the Arduino model) and stores the result in the variable light.
Serial.println(light); outputs the value of the variable light to the Arduino's serial port. This is a standard way of outputting data from the Arduino so that it can be displayed on a connected computer.
analogWrite(3, light/4); outputs the value of light/4 as a phase-width modulated (PWM) signal to pin 3. Although Arduino output pins are either on (5 volts) or off (ground) at any point in time, PWM signals allow the Arduino to switch an output pin on and off rapidly so that the average voltage seen on that pin is an intermediate value. The duty cycle of the PWM signal which determines the average voltage on the pin is encoded as an 8 bit integer, so light is probably divided by 4 here to convert it from 10 bits to 8 bits.
So the Arduino will repeatedly read an input voltage from pin 5, output an integer representing this voltage to the serial port, and create a PWM signal on pin 3 that has an average voltage the same as that of the input voltage.
See the Arduino language reference page for more information.

Great answer.  What are all the dollar signs for?

@CrossRoads, The question and the answer were migrated from physics.stackexchange.com. In that forum, the server will use MathJax to render any text enclosed by dollar signs as mathematical equations. It's not unusual for people on that site to use MathJax even for an "equation" that is just a single, literal constant.

To make the answer clearer I have removed the MathJax markup and made other small formatting changes.


text:
Difference in increment & decrement loop execution speed
I was experimenting with for loops when I noticed that a simple increment loop executes faster than a decrement loop. I can't think of any reason why it should be like that. Is there something in my code that is causing the different in execution speed?
The code is as follows:
// Global Variables
const int spk = 7;
const int led = 6;
int j = 0; // counter variable

void setup() {

  pinMode(spk, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
} // end of setup

void loop() {

  tone(spk, 300, 500); // first note with duration

  // increment loop
  for (j=0; j <= 500; j = j + 1) {
    digitalWrite(led, HIGH);
    Serial.println(j);
  } // end 1st note loop

  tone(spk, 100, 500); // second note with duration

  // decrement loop

  for (j = 500; j >= 0; j=j-1) {
    digitalWrite(led, LOW);
    Serial.print("the value is=");
    Serial.print("\t");
    Serial.println(j);
  } // end 2nd Note loop

} // end setup

Comment out these 2 lines
Serial.print("the value is=");
Serial.print("\t");

And report back on the speed difference.
Why not add a reading of micros() before and after each loop and see how much difference there really is?  All time variables are unsigned long.
startTime = micros();
// your loop
endTime =  micros();
duration = endTime - startTime;
Serial.println (" "); // line break
Serial.print ("duration in uS = ");
Serial.println (duration);

I edited to add some missing )s and a 2nd line break.

Yes the extra serial prints in the decrement loop were adding the extra time. However, after adding the mircros before and after each loop and removing all extra print statements I still find the decrement loop takes 60  to 80 microsecond longer. Is it usual?

I don't know.  I don't think I've ever used a decrementing for:next loop.  Might also be something with setting a pin low vs high.  You could try fastdigitalWrite() instead, see if that makes a difference (in the IDE already? maybe have to pull it from guthub?).  There is a way to look at the assembly code that is created, see what is actually being run.  Nick Gammon used to post examples like that, not sure how he got the assembly out of the compile process.

Ah it's fine :) Doesn't really make that big of a difference for now. Going after the assembly code would be too complicated and don't even know how to go about it.

In the code you posted, the decrement loop has two more Serial.print() statements.
Serial.print() takes a lot of time and while it's useful for debugging, it sometimes can cause additional bugs because of the extra delay it introduces if you are running time-sensitive code.
Consider for using Serial.print("the value is=\t" + itoa(j,10));
"itoa" converts an integer to an array of characters (aka string). As Juraj said, it takes another two arguments which are the buffer to store the output string and the base to which it converts the incoming number to be represented by (eg: 10 is decimal, 16 is hexadecimal). It returns a pointer to the output string which is essentially the same as the second argument but AFAIR you can omit the second argument and use it's return value.

+ doesn't concatenate char arrays. itoa has more parameters


text:
How to make an arduino button to forget his past purpose?
For my school project im making an arduino speedometer for a bicycle. I will be using a reed switch sensor to get the speed. There will also be an clock and a termometer, it will be on a 16x2 lcd screen. To get the speed I will need the user to type in his bike size, in zoll. I managed to let the user tap the button until his size and then double tap the button to confirm it. Alright, fine. Now I need the same button to FORGET his last purpose. Because I want to use the same button to change the screen between speed, clock and termometer. SPEED -> tap -> CLOCK -> tap -> TEMPERATURE -> tap -> SPEED ........
I hope you get the idea. After the user picks his size, if he keeps tapping the number it would just keep on growing. So, im trying to make the button forget, or make him go trough that loop only once.
Pick your size tap tap tap double tap, thank you. And stop! I want him to do that only once and never again. I will need the same principle when the user will adjust his clock, he will have to tap to set it, save the number but reset the buttons function.
#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
LiquidCrystal_I2C lcd(0x27, 16,2);
#define buttonPin 7
int a = 16;
int b = 0;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("RADGROESSE IN");
  lcd.setCursor(0, 1);
  lcd.print("ZOLL EINGEBEN");

   // Set button input pin
   pinMode(buttonPin, INPUT);
   digitalWrite(buttonPin, HIGH );
}
void loop() {
   int b = checkButton();
   if (b == 1) clickEvent();
   if (b == 2) doubleClickEvent();
}
void clickEvent() {

   lcd.setCursor(14, 1);
    lcd.print(a);
    delay(100);
    lcd.print(" ");
    delay(100);
    a++;
    delay(100);
    if(a >= 23){
      a = 16;
      }
}
void doubleClickEvent() {
      b = a - 1;
      Serial.println("Button was idle for one second or more");
      lcd.clear();
      lcd.print("ZOLL = ");
      lcd.setCursor(7, 0);
      lcd.print(b);

}

//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 420;            // max ms between clicks for a double click event
// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released

int checkButton() {
   int event = 0;
   buttonVal = digitalRead(buttonPin);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       singleOK = true;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
   }
   // Test for normal click event: DCgap expired
   if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
   {
       event = 1;
       DCwaiting = false;
   }

   buttonLast = buttonVal;
   return event;
}

Thank you! I would really appreciate it!

When exactly does the user need to enter the bike size again? After restart / reset of Arduino? Or do you want the user to double click only once?

buttons do not have a memory ... there is nothing to forget ... the program has to respond to a button press depending on the state the program is in

Yes, after the reset. I want the user to tap until his size and double tap to save the size.
After that the bike size part shouldnt come across ever again, well of course if you reset it, but that wont be the case.
After you choose the size the button will now work as a skip function.
I basically want to change the function of a button.

jsotola wrote a very important term in the comments: state.
You should implement your project as a Finite State Machine (FSM), a very important and powerful, yet easy principle. You divide your program into different states. Each state contains code, that only gets executed, when the program is in this state. Depending on input events (like the user pressing the button), you do transitions between the states.
I already wrote a rather detailed answer about FSMs for this question. You can read it to get a better understanding of FSMs.
For your case I would suggest these states: INPUT_SIZE, DISPLAY_SPEED, DISPLAY_CLOCK and DISPLAY_TEMPERATURE. INPUT_SIZE is the initial state (which you might skip after the first power on, after you saved the size in persistent memory like EEPROM). There you execute your current button code. When you sense a double tap on the button, you change to the DISPLAY_SPEED state. From there on a button press to the DISPLAY_CLOCK state and so on.
In my linked answer I used a simple integer variable as state variable, which holds the current state. In fact it is better (easier to read), when you define an enum for the cases (enums are actually only named integer constants):
enum State {INPUT_SIZE, DISPLAY_SPEED, DISPLAY_CLOCK, DISPLAY_TEMPERATURE};

State state = INPUT_SIZE;

void loop(){
    switch(state){
        case INPUT_SIZE:
            // Button code here
            // on double tap use the following line
            state = DISPLAY_SPEED;
            break;
        case DISPLAY_SPEED:
            // code for displaying speed here
        ...
    }
}

That is just a little template for the structure. You need to fill it with life yourself.

Yes, exactly what I needed. Alright, thank you, I will study it, look online and try to implement it
THANK YOU

What you likely need is a state machine. The behavior of the actions depends on the state the program is currently in.
In your case, the state machine might look like this:

What does it mean?

black circle: this is where the system powers on
rectangle: a state
arrow: a transition from one state to another
green text: action

For the problematic double click action, you can see:

it changes the state from "set size" to "speed"
in all other cases, it does not change the state (actually it changes the state to the same state)

I always recommend drawing the state machine before implementing it. It makes mistakes much more obvious.
There are several ways to implement it. The easiest one being a switch/case. More advanced implementations may use object orientation. When using switch/case, I prefer to have one method per state, like so:
void loop()
{
    switch(state):
        case setsize:
             setsize();
             break;
        case speed:
             speed();
             break;
        ...
}

If you know about function pointers, it gets even easier:
enum State {
  setsize = 0,
  speed,
  clock,
  temperature
};

State state;

void setup() {
  state = State::setsize;
}

typedef void (* functionPointer) ();
functionPointer process[] = {do_setsize, do_speed, do_clock, do_temperature};
void loop() {
  process[state]();
}

void do_setsize()
{
  state = State::speed;
}
void do_speed()
{
  state = State::clock;
}
void do_temperature()
{
  state = State::speed;
}
void do_clock()
{
  state = State::temperature;
}

Thank you. I managed to get it to work. Thank you!


text:
Binary to decimal using bitwise operators
I am trying to convert some binary data to decimal numbers. I succeeded to convert binary to hex, but now I want to do the same with binary to decimal. I want to use bitwise operators and NO array.
See my code from binairy to hex. The incoming data is 8 bits. This code first calculates the most significant number, and then, the least significant number. This works good, but I cannot figure it out for bin to dec
The function console_print_char is sort of the printf function of my program.
    void console_print_hex_char(unsigned char data){
    unsigned char temp;

    if(data){
        temp = (data >> 4);
        if(temp){
            if(temp> 9) console_print_char(temp + ('A'- 10));
            else console_print_char(temp + '0');
        }
        temp = data & 0x0F;
        if(temp> 9) console_print_char(temp + ('A'- 10));
        else console_print_char(temp + '0');
    }
    else{
        console_print_char('0');
    }
}

your question is a general programming question that is not related to the Arduino ... please delete your post and go here https://stackoverflow.com/questions

note: you have a stray }, that is outside of the "code area"  of your post

@jsotola is right, you might need to push this over to SO. Anyway, the conversion of a binary number into decimal is most simply done with modulo (%) and divide (/) if you don't want to use library functions. Additionally, there is an algorithm that involves shifting bit by bit, and some conditional adding of 3. Unfortunately I don't have an URL at hand.

Binary is spelled B-I-N-A-R-Y. It's bi-na-ry, not bin-air-y.

You can google Binary to BCD conversion. There are pretty short algorithms that do this. After the conversion each decimal digit is stored in a nibble.

You cannot do what you are trying to do. There is no direct correspondence between some number of bits and a decimal digit.
With hexadecimal, every 4 bits corresponds to exactly 1 hex digit. That is why hex is used for computers.
One hex digit represents exactly 4 bits. Every time you add another hex digit, you add 4 bits.
Two hex digits corresponds to exactly a byte. 00h to FFh represents a value from 0 to 255.
There is no such direct correspondence between binary and decimal. If you have 4 bits, it takes 1 or 2 decimal digits to represent it (0-15) If you have 8 bits, it takes 1, 2, or 3 decimal digits to represent it, but there are 3 digit decimal values (values > 255) that you can't represent with 8 bits.
Binary  Hex Decimal
0000    0   0
0001    1   1
0010    2   2
0011    3   3
0100    4   4
0101    5   5
0110    6   6
0111    7   7
1000    8   8
1001    9   9
1010    A   10
1011    B   11
1100    C   12
1101    D   13
1110    E   14
1111    F   15

You simply cannot convert a binary number to decimal using bit shifting and masking.
As @Kwasmich says in their answer, the closest you're likely to come would be to convert your binary value to BCD (Binary coded decimal) where each 4 bits holds a decimal digit. You could convert THAT to decimal character output using masking and shifting.

here's the c++ code
    vector<int> b={1,0,1,0,1,0,1};
        int sum=0;
        for(int i=b.size()-1, j=0; i>=0; i--, j++){
            sum+=b[j]*(1<<i);
        }
        return sum;

That is a way to convert a series of bits to decimal. Note the it uses multiplication and arrays, both of which the OP wants to avoid.

BTW, it's silly to use b[j] * (1<<i). That's an unneeded multiplication. Just use sum += b[j]<<iIfb[j]is 0, it shifts nothing for that bit. Ifb[j]` is a 1 bit, it shifts a one to the appropriate magnitude, without the need of a multiply.


text:
Multiple devices on 5v pin
Im soldering an LCD screen to my Arduino as I don't have a breadboard and plan on it being permanent. I'm wondering how I should connect the potentiometer (to control contrast).
If I connect it as the first component in series, will this affect the main power to the LCD?
Should I use both 5v pins on the Arduino instead? (Mine has two anyway, I dont know if the official one does).
Would splitting a cable work?
Im new to electronics so sorry if the questions are stupid.
I intend to use the circuit from: https://www.arduino.cc/en/Tutorial/HelloWorld.
Thanks for any help.

why would the potentiometer be in series with the LCD? ... it is not is series in the circuit that you linked

I meant it as an option as I'm unsure of connecting in parallel. A better question would be how can I connect two things to the 5v. Sorry and thanks!

use two wires ... i do not understand what you are really asking

yes, you can connect several things to the 5v line, within current limits of course.

@dandavis would you mind helping me with this? I would be connecting the vdd and anode pins of the lcd to the 5v aswell as the 5v of a humidity sensor. Is this too much? Thanks

since neither of those devices use very much power, you're good.

Thank you very much!

Related article I wrote: https://www.electricrcaircraftguy.com/2014/02/arduino-power-current-and-voltage.html


text:
Sleep mode and watchdog at the same time
Suppose we want to save battery power, and we use sleep mode and also prevent the Arduino from hanging and use the watchdog timer.
The problem is here that when the Arduino goes to sleep the watchdog timer never (or can't be) reset again because of sleep and it will overflow over and over and reset the Arduino over and over.
So what do you suggest to solve this problem, I mean running sleep mode and watchdog timer at the same time in a code?

Please show us the sketch you're using.

When you sleep the Arduino is locked up. So yes, the watchdog timer will time out and reset the Arduino.
But, since you're in sleep mode, it's not so much a "reboot" as a "wakeup".
The watchdog timer is one of the normal ways of waking up periodically to do things.  If you want to use the watchdog for its other "anti-lockup" purpose then you will have to arrange some other way of waking up before the watchdog is due to expire so you can "kick" it.
Or you disable the watchdog entirely before going to sleep so that the only wakeup source is whatever source you have configured. Then you can turn the watchdog on again when you wake up.
However that probably means that the watchdog is useless, since chances are you won't be awake for long enough periods for the watchdog to have any effect.
Sleeping and using the internal watchdog as a watchdog are pretty much mutually exclusive.  If you sleep, then the watchdog is a periodic wake-up source.

If you set the arduino to sleep while the watchdog is running, the arduino will reset after the set amount of time. Unless you set the watchdog to trigger an interrupt. The watchdog isn't a wake-up source, unless you set it up as one. Also note that the watchdog unsets the interrupt when triggered. This is so that, if the program hangs, the first timeout it will call the interrupt, and the second timeout will cause a reset.

Either set the watchdog to 8s, and setup the WDT interrupt. And deal with the fact that the MCU wakes up every 8s. You could have it go back to sleep, unless a button is pressed, or something. The extra power usage for these short wakeups is negligible in most cases.
Or disable the watchdog right before sleeping, and enable right after waking up. And hope the MCU never hangs in between.

the periodically reset(or reboot) doesn't hurt the MCU?

No. Won't hurt the MCU.


text:
I am facing a problem of firing multiple interrupts on nodemcu 1.0 on single rising edge pulse.what is problem and what are the solutions?
I am working on a project which involves counting the drops falling in a drip chamber of a IV fluid gravity based therapy bottle(saline bottle).I am using IR trans-receiver at the drip chamber to detect a drop falling. I am using a comparator to generate a pulse when ir voltage drops below a certain threshold. The output of comparator is connected to D1 of nodemcu. The ISR is called at rising pulse of comparator .But the nodemcu calls the ISR 3 to 5 times on a single drop.what should I do?plz help.

It sounds, like your circuit is producing multiple rising edges per drop. You could check that, by watching the signal through an oscilloscope or a logic analyser. The cleanest way of solving would be to tweak your circuit, so that you only get 1 rising edge per drop. Or you can turn of the interrupt for a specific time, after the first drop detection (so that you ignore the false interrupts

Seems good I'll try it.i should turn off the interrupt using micros after a drop detected and again turn on the interrupt after some milli second. I can' t stop running the main loop as it consist of sending the data volume remain, rate, etc. to the database.

what is the fastest drip rate of a saline IV?

Actually I didn't have the perfect idea .I googled it, but i didn't get the direct ans. Then I saw "dial a flow " tubing images, it has max. 250 ml/ hr mark on it. And from Google I got to know the max drop factor (drops required for 1 ml ) is 60. From this i calculated the max drip rate could be 4 to 5 drops per second.

might try a small capacitor, like 1 or 0.1uf on the ir voltage to slow it down and filter out noise. you essentially need a 10hz low pass filter. also the 8266's ADC only likes to sample about 800 times a second, asking it more might produce erratic results.

The signal is probably "bouncing" between HIGH and LOW instead of performing a clean edge, just like it happens with buttons.
Two simple solutions:

Hardware solution: use a schmidt-trigger instead of a comparator
Software solution: define a dead-time for the signal aquisition (disable the interrupt when the desired edge has been detected and enable it again after "dead-time")

I will try  both of the solutions.   was first using the adc on the nodemcu.but for that the nodemcu was missing the drops .so to use the interrupt I have to use comparator.

Sim Son,I can disable the interrupt in isr .but how to reenable it without stopping the main loop because checking the condition that deadtime is completed will not allow to do other things? I am not able to write code for that can u elaborate.


text:
Interrupts inside a class attaching to the function of the class
Hello i have a class and i would like to attach an interrupt inside the class and attach it to a function of the class.
class counter{
  public:

  counter(int pin){
    Ipin=pin;
  }
  void startCounting(){
    attachInterrupt(digitalPinToInterrupt(Ipin),this.addCount,CHANGE);
  }
  void stopCounting(){
    detachInterrupt(digitalPinToInterrupt(Ipin));
  }

  void addCount(){
    count++;
  }

  private:
  int Ipin;
  unsigned long count= 0;
};

Some what of the code above. There can be multiple intialization of this class. hopefully depending on the user uses a different pin.
There is a way arround this where the attaching of pin is done in the loop or setup and just calling a public function of the class. But to me that kinda doesn't fit the spirit of classes like a properly made library is done.
Im not very good at programming if you could teach me how it would be greatly appreciated.

I's not supported by attachInterrupt. You need some function that calls that desired method.

@KIIV so how do libraries with interrupts do it?

By using some function that calls method on specific object. You can't use more callbacks for the same interrupt source anyway.

So if we go by what you have said and to lets say i were to create a library. I would have 2 fuunctions that does not belong to any class in the .h or .cpp that  first function attaches the interrupt to the second function, and that second function calls a method of the class?? Is it possible to call a global function inside of a class?

I have a post about this problem.
Basically you cannot attach a class function with attachInterrupt because of the hidden "this" pointer which needs to be supplied to a (non-static) class function, where "this" is the particular instance of the class. You can work around it like this:
class myClass
  {
  static volatile bool switchChanged;  // declare

  public:

  void begin ()
    {
    pinMode (2, INPUT_PULLUP);
    attachInterrupt (0, switchPressed, CHANGE);
    }  // end of myClass::begin

  static void switchPressed ()
    {
    switchChanged = true;
    }  // end of myClass::switchPressed

  };  // end of class myClass

volatile bool myClass::switchChanged;  // define

myClass foo;  // make an instance of myClass

void setup ()
  {
  foo.begin ();
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

But that isn't great because, as you observed, you are really downgrading the class to use a static boolean.

Another way of doing it is to write "glue" routines, like this:
class myClass
  {
  volatile bool switchChanged;

  static myClass * instances [2];

  static void switchPressedExt0 ()
    {
    if (myClass::instances [0] != NULL)
      myClass::instances [0]->switchPressed ();
    }  // end of myClass::switchPressedExt0

  static void switchPressedExt1 ()
    {
    if (myClass::instances [1] != NULL)
      myClass::instances [1]->switchPressed ();
    }  // end of myClass::switchPressedExt1

  public:

  void begin (const byte whichPin)
    {
    pinMode (whichPin, INPUT_PULLUP);
    switch (whichPin)
      {
      case 2:
        attachInterrupt (0, switchPressedExt0, CHANGE);
        instances [0] = this;
        break;

      case 3:
        attachInterrupt (1, switchPressedExt1, CHANGE);
        instances [1] = this;
        break;

      } // end of switch
    }  // end of myClass::begin

  void switchPressed ()
    {
    switchChanged = true;
    }

  };  // end of class myClass

myClass * myClass::instances [2] = { NULL, NULL };

// instances of our class
myClass foo;
myClass bar;

void setup ()
  {
  foo.begin (2);   // pin D2
  bar.begin (3);   // pin D3
  }  // end of setup

void loop ()
  {
  // whatever
  }  // end of loop

That's still not a great solution, but it might give you some ideas.

Your fundamental problem is that classes, by their nature, can be instantiated many times, however you only have a small, fixed, number of interrupts on the microprocessor.

Thank you for the great reference, the "glue" solution would work for me because i  am using a custom built board and there is a fix number of pins to interrupt. I just want to take the trouble off the user when using the library, when begin is called on my main class all the interrupts should be ready to go. Atleast i wont have to make a function on all interrupt pins (60+ pins = 60+ functions on due). Thank you again for the answer.

I can understand it would cause trouble where the number of instantiation would exceed the number of interrupts the processor. Although that can be fixed by adding protection macros that throws an error if the number of instantiation exceed the number of interrupts,but that would be a lot of macros for each board you want your class to work.


text:
Connect more than 4 BLE clients to ESP32 BLE Server
I want to create some buzzers connected via bluetooth for a quiz show. I got several ESP32. One of them is the master (BLE Server), the other ESP32s are the buzzers (BLE Clients) with one big button and some LEDs each. The master sends commands ("turn on", "turn off", "you are number x") to all the buzzers and receives when one of them gets pressed.
The code on both sides works for up to 4 clients, but I can't connect more than 4 BLE clients to the BLE server.
I found and changed the CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN and CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF in sdkconfig.h at C:\Users\MyName\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\tools\sdk\include\config.
This seems to be the right place, because both values originally were 3 and then only three clients could connect. The fourth client was rejectet (got a false on pClient->connect(myDevice);). When I updated both numbers to 4, the fourth client could connect and could receive the notifications from the server.
Then I changed these two numbers to 8, because I potentially want to connect even more buzzers. But the 5th buzzer could not connect. It got a true on pClient->connect(myDevice);, but it would not receive any notifications from the server. A few seconds later it starts looking for a server again. The server also does not recognize the 5th client (for client 1 to 4 the server prints Device connected. Now there are x devices connected., but not so for the 5th client)
This is my servers code
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#define DEBUG
#define VERSION "0.1"

#define BUZZER_SERVICE_UUID "a2066d3e-d566-42bd-9d64-9bf3ae53b504"
#define COMMAND_CHAR_UUID   "e7adc44d-a04e-46b1-aa4b-ded61bc3b0a8"
#define RESPONSE_CHAR_UUID  "e7adc44d-a04e-46b1-aa4b-ded61bc3b0a9"

#define PIN_BUTTON_ARM 23
#define PIN_BUTTON_DISARM 22

BLEServer* pServer = NULL;
BLECharacteristic* pCommandCharacteristic = NULL;
BLECharacteristic* pResponseCharacteristic = NULL;
int deviceConnected = 0;
bool oldDeviceConnected = false;

bool armPressed = false;
bool disarmPressed = false;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer)
    {
        deviceConnected++;
        BLEDevice::startAdvertising();
        #ifdef DEBUG
        Serial.print("Device connected. Now there are ");
        Serial.print(deviceConnected);
        Serial.println(" devices connected.");
        #endif
    };

    void onDisconnect(BLEServer* pServer)
    {
        deviceConnected--;
        pServer->startAdvertising(); // restart advertising
        #ifdef DEBUG
        Serial.print("Device disconnected. Now there are ");
        Serial.print(deviceConnected);
        Serial.println(" devices connected.");
        #endif
    };
};

class MyCharCallbacks: public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pCharacteristic)
    {
        std::string rxValue = pCharacteristic->getValue();
        Serial.print(">>> ");
        Serial.println(rxValue.c_str());

        if (rxValue.length() > 0)
        {
            //TODO
        }

    }
};

void setup()
{
    #ifdef DEBUG
    Serial.begin(115200);
    Serial.println("\n\n--------------");
    Serial.println("BUZZER HUB");
    Serial.println("--------------");
    Serial.print("VERSION: ");
    Serial.println(VERSION);
    Serial.println("--------------");
    #endif

    pinMode(PIN_BUTTON_ARM, INPUT_PULLUP);
    pinMode(PIN_BUTTON_DISARM, INPUT_PULLUP);

    BLEDevice::init("BuzzerHub");
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    BLEService *pService = pServer->createService(BUZZER_SERVICE_UUID);

    // Create a BLE Characteristic and a BLE Descriptor for sending the commands
    pCommandCharacteristic = pService->createCharacteristic(COMMAND_CHAR_UUID, BLECharacteristic::PROPERTY_NOTIFY);
    pCommandCharacteristic->addDescriptor(new BLE2902());

    // Create a BLE Characteristic and a BLE Descriptor for receiving the responses
    pResponseCharacteristic = pService->createCharacteristic(RESPONSE_CHAR_UUID, BLECharacteristic::PROPERTY_WRITE);
    pResponseCharacteristic->addDescriptor(new BLE2902());
    pResponseCharacteristic->setCallbacks(new MyCharCallbacks());

    //Start the service
    pService->start();

    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(BUZZER_SERVICE_UUID);
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);
    BLEDevice::startAdvertising();

    #ifdef DEBUG
    Serial.println("BLE is now advertising");
    #endif
}

void loop()
{
    if(digitalRead(PIN_BUTTON_ARM) == LOW)
    {
        if(!armPressed) //On pressing the button
        {
            armBuzzer();
            delay(100); //Debounce
        }
        armPressed = true;
    }
    else
    {
        if(armPressed) //On releasing the button
        {
            delay(100); //Debounce
        }
        armPressed = false;
    }

    if(digitalRead(PIN_BUTTON_DISARM) == LOW)
    {
        if(!disarmPressed) //On pressing the button
        {
            disarmBuzzer();
            delay(100); //Debounce
        }
        disarmPressed = true;
    }
    else
    {
        if(disarmPressed) //On releasing the button
        {
            delay(100); //Debounce
        }
        disarmPressed = false;
    }
}

void armBuzzer()
{
    if (deviceConnected)
    {
        #ifdef DEBUG
        Serial.println("<<< ARM");
        #endif
        pCommandCharacteristic->setValue("ARM");
        pCommandCharacteristic->notify();
        //delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
    }
}

void disarmBuzzer()
{
    if (deviceConnected)
    {
        #ifdef DEBUG
        Serial.println("<<< DISARM");
        #endif
        pCommandCharacteristic->setValue("DISARM");
        pCommandCharacteristic->notify();
        //delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
    }
}

And this is my clients BLE part of the code (there is more, but that got nothing to do with BLE)
// The buzzer service we wish to connect to.
static BLEUUID buzzerServiceUUID("a2066d3e-d566-42bd-9d64-9bf3ae53b504");
// The characteristic of the buzzer service that is there for receiving commands from the hub.
static BLEUUID buzzerCommandCharUUID("e7adc44d-a04e-46b1-aa4b-ded61bc3b0a8");
// The characteristic of the buzzer service that is there for sending commands to the hub.
static BLEUUID buzzerResponseCharUUID("e7adc44d-a04e-46b1-aa4b-ded61bc3b0a9");

static BLERemoteCharacteristic* pCommandCharacteristic;
static BLERemoteCharacteristic* pResponseCharacteristic;
static BLEAdvertisedDevice* myDevice;
String message;
bool newMessage;

static boolean doConnect = false;
static boolean connected = false;

static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify)
{
    #ifdef DEBUG
    /*
    Serial.print("Notify callback of data length ");
    Serial.println(length);
    Serial.print("data: ");
    Serial.println((char*)pData);
    */
    #endif
    message = "";
    for(int i = 0; i < length; i++)
    {
        message += (char)pData[i];
    }
    message += '\0';
    newMessage = true;
}

class MyClientCallback : public BLEClientCallbacks {
    void onConnect(BLEClient* pclient)
    {
        connected = true;
        setMiddleLed(0,255,0);
        #ifdef DEBUG
        Serial.println("onConnect");
        #endif
    }

    void onDisconnect(BLEClient* pclient)
    {
        connected = false;
        setMiddleLed(255,0,0);
        updatePattern = false;
        #ifdef DEBUG
        Serial.println("onDisconnect");
        #endif
    }
};

//Scan for BLE servers and find the first one that advertises the service we are looking for.
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
    //Called for each advertising BLE server.
    void onResult(BLEAdvertisedDevice advertisedDevice)
    {
        #ifdef DEBUG
        Serial.print("Advertised Device found: ");
        Serial.println(advertisedDevice.toString().c_str());
        #endif

        // We have found a device, let us now see if it contains the service we are looking for.
        if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(buzzerServiceUUID)) // Found our server
        {
            BLEDevice::getScan()->stop();
            myDevice = new BLEAdvertisedDevice(advertisedDevice);
            doConnect = true;
        }
    }
};

bool connectToServer()
{
    #ifdef DEBUG
    Serial.print("Connecting to ");
    Serial.println(myDevice->getAddress().toString().c_str());
    #endif

    //Create Client
    BLEClient*  pClient  = BLEDevice::createClient();
    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remote BLE Server.
    bool ok = pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    if (!ok)
    {
        #ifdef DEBUG
        Serial.print("Failed to connect to address: ");
        Serial.println(myDevice->getAddress().toString().c_str());
        #endif
        pClient->disconnect();
        return false;
    }

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(buzzerServiceUUID);
    if (pRemoteService == nullptr)
    {
        #ifdef DEBUG
        Serial.print("Failed to find our service UUID: ");
        Serial.println(buzzerServiceUUID.toString().c_str());
        #endif
        pClient->disconnect();
        return false;
    }

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pCommandCharacteristic = pRemoteService->getCharacteristic(buzzerCommandCharUUID);
    if (pCommandCharacteristic == nullptr)
    {
        #ifdef DEBUG
        Serial.print("Failed to find command characteristic UUID: ");
        Serial.println(buzzerCommandCharUUID.toString().c_str());
        #endif
        pClient->disconnect();
        return false;
    }

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pResponseCharacteristic = pRemoteService->getCharacteristic(buzzerResponseCharUUID);
    if (pResponseCharacteristic == nullptr)
    {
        #ifdef DEBUG
        Serial.print("Failed to find response characteristic UUID: ");
        Serial.println(buzzerResponseCharUUID.toString().c_str());
        #endif
        pClient->disconnect();
        return false;
    }

    //Register the notification
    if(pCommandCharacteristic->canNotify()) pCommandCharacteristic->registerForNotify(notifyCallback);

    return true;
}

void setupBle()
{
    String name = "Buzzer" + String(dipNumber);
    BLEDevice::init(name.c_str());

    scanForServer();
}

void scanForServer()
{
    #ifdef DEBUG
    Serial.println("Scanning for Server...");
    #endif

    setMiddleLed(0,0,255);
    updatePattern = false;

    // Retrieve a Scanner and set the callback we want to use to be informed when we
    // have detected a new device.  Specify that we want active scanning and start the
    // scan to run for 5 seconds.
    BLEScan* pBLEScan = BLEDevice::getScan();
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan->setInterval(1349);
    pBLEScan->setWindow(449);
    pBLEScan->setActiveScan(true);
    pBLEScan->start(5, false);
}

void loopBle()
{
    // If the flag "doConnect" is true then we have scanned for and found the desired
    // BLE Server with which we wish to connect.  Now we connect to it.
    if (doConnect == true)
    {
        if (connectToServer())
        {
            #ifdef DEBUG
            Serial.println("Connected to server.");
            #endif
        }
        else
        {
            #ifdef DEBUG
            Serial.println("Failed to connect to server.");
            #endif
        }
        doConnect = false;
    }

    if(!connected)
    {
        delay(100);
        setMiddleLed(255,0,0);
        delay(900);
        scanForServer();
    }
}

void sendData(String stringToSend)
{
    // Only send when connected
    if (connected)
    {
        //Set the characteristic's value to be the array of bytes that is actually a string.
        pResponseCharacteristic->writeValue(stringToSend.c_str(), stringToSend.length());
        #ifdef DEBUG
        Serial.print("<<< ");
        Serial.println(stringToSend);
        #endif
    }
    else
    {
        #ifdef DEBUG
        Serial.println("Can't Send because not connected");
        Serial.print("XXX ");
        Serial.println(stringToSend);
        #endif
    }
}

How can I connect more clients to my BLE server? What is the maximum number?
Thanks for your help!

The SDK only allows 4 connections. You might be better off creating a mesh instead, but for that you'd need to switch over to the ESP-IDF.


text:
How to get my LCD contentiously updating with data from sensor?
EDIT DOWNSTAIRS:
Hello beautiful people of the internet! How are you smart people doing with all that's going on these days. Okay so the title says it pretty much. I've got a code and inside of my if's I have added something that lets me see the data from the sensor in percentage on my LCD. It works but it just stays at the number it read when it went on that mode. How do I make it so it starts "updating" automatically.
Sooo I am talking about this part mostly (and other exactly like it)
    if (whichPlant == 2) {
      lcd.setRGB(plant3R, plant3G, plant3B);
      lcd.clear();
       lcd.display();
      lcd.print("Orchid");// print the results to the LCD Display:
      sensorValue = analogRead(waterSensorPin);// read the analog in value:
      sensorValue = map(sensorValue, 0, 750, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }

And here is my entire code if you're interested
#include <Servo.h>

#include <Wire.h>
#include "rgb_lcd.h"
rgb_lcd lcd;

const int numberOfPlants = 4;
const int noPlant = -1;  // index meaning no plant is being monitored

const int plant1R = 0;
const int plant1G = 0;
const int plant1B = 255;
const int zeroR = 0;
const int zeroG = 0;
const int zeroB = 0;
const int plant2R = 0;
const int plant2G = 255;
const int plant2B = 0;
const int plant3R = 255;
const int plant3G = 0;
const int plant3B = 0;
const int plant4R = 255;
const int plant4G = 0;
const int plant4B = 255;

// Pinout.
const int waterSensorPin = A1;
const int buttonPin = 2;
const int servoPin = 5;
const int ledPins[numberOfPlants] = {12, 11, 10, 9};

// Moisture ranges for the different plants.
const int moistureMinima[numberOfPlants] = {  0,   0,   0,   0};
const int moistureMaxima[numberOfPlants] = {195, 682, 750, 950};

// Servo holding the indicator needle.
Servo indicator;
int sensorValue = 0; // value read from the Soil Moisture
void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);
  pinMode(waterSensorPin, INPUT);
  pinMode(buttonPin, INPUT);
  for (int ledNo = 0; ledNo < numberOfPlants; ledNo++) {
    pinMode(ledPins[ledNo], OUTPUT);
  }
  indicator.attach(servoPin);
}

void loop() {
  // Which plant are we currently monitoring?
  static int whichPlant = noPlant;
  // Switch to next plant on button press.
  if (digitalRead(buttonPin) == HIGH) {
    if (whichPlant != noPlant) {
      digitalWrite(ledPins[whichPlant], LOW);  // turn off previous LED
    }
    ++whichPlant;
    if (whichPlant == numberOfPlants) {
      whichPlant = noPlant;
    } else {
      digitalWrite(ledPins[whichPlant], HIGH);  // turn on current LED
    }
    if (whichPlant == 3) {

      digitalWrite(10, HIGH);  // turn off previous LED
      digitalWrite(12, HIGH);  // turn off previous LED
      lcd.setRGB(plant4R, plant4G, plant4B);
      lcd.clear();
       lcd.display();
      lcd.print("Swamp Plant");// print the results to the LCD Display:
      sensorValue = analogRead(waterSensorPin);// read the analog in value:
      sensorValue = map(sensorValue, 0, 950, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
      delay(500);  // crude debouncing
    }
    if (whichPlant == 2) {
      lcd.setRGB(plant3R, plant3G, plant3B);
      lcd.clear();
       lcd.display();
      lcd.print("Orchid");// print the results to the LCD Display:
      sensorValue = analogRead(waterSensorPin);// read the analog in value:
      sensorValue = map(sensorValue, 0, 750, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }
    if (whichPlant == 1) {
      lcd.setRGB(plant2R, plant2G, plant2B);
     lcd.clear();
      lcd.display();
      lcd.print("Sunflower");// print the results to the LCD Display:
      sensorValue = analogRead(waterSensorPin);// read the analog in value:
      sensorValue = map(sensorValue, 0, 682, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }
    if (whichPlant == 0) {
      lcd.setRGB(plant1R, plant1G, plant1B);
     lcd.clear();
      lcd.display();
      lcd.print("Orchid");// print the results to the LCD Display:
      sensorValue = analogRead(waterSensorPin);// read the analog in value:
      sensorValue = map(sensorValue, 0, 195, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }

  }
  if (whichPlant == noPlant) {
    digitalWrite(10, LOW);  // turn off previous LED
    digitalWrite(12, LOW);  // turn off previous LED
    lcd.clear();
    lcd.noDisplay();
    lcd.setRGB(zeroR, zeroG, zeroB);

  }
  // Report the moisture level of this plant.
  if (whichPlant != noPlant) {
    int sensorValue = analogRead(waterSensorPin);
    int position = map(sensorValue,
                       moistureMinima[whichPlant], moistureMaxima[whichPlant], 180, 0);
    indicator.write(constrain(position, 0, 180));
    Serial.println(sensorValue);
    delay(500);

  }
  // added 14-02 to make sure servo pointer goes back to start after reading last reading from waterSensor
  if (whichPlant == noPlant) {
    int sensorValue = analogRead(waterSensorPin);
    int position = map(sensorValue,
                       moistureMinima[whichPlant], moistureMaxima[whichPlant], 180, 0);
    indicator.write(constrain(position, 180, 180));
    delay(500);

  }

  //gemaakt door Sinan van Noppen
}

and if you have any suggestions or you have a go on making my code better, more DRY I would be honoured and appreciate it :)
EDIT: (just changed the place of the if whcihplant == 3 etc.)
#include <Servo.h>

#include <Wire.h>
#include "rgb_lcd.h"
rgb_lcd lcd;

const int numberOfPlants = 4;
const int noPlant = -1;  // index meaning no plant is being monitored

const int plant1R = 0;
const int plant1G = 0;
const int plant1B = 255;
const int zeroR = 0;
const int zeroG = 0;
const int zeroB = 0;
const int plant2R = 0;
const int plant2G = 255;
const int plant2B = 0;
const int plant3R = 255;
const int plant3G = 0;
const int plant3B = 0;
const int plant4R = 255;
const int plant4G = 0;
const int plant4B = 255;

// Pinout.
const int waterSensorPin = A1;
const int buttonPin = 2;
const int servoPin = 5;
const int ledPins[numberOfPlants] = {12, 11, 10, 9};

// Moisture ranges for the different plants.
const int moistureMinima[numberOfPlants] = {  0,   0,   0,   0};
const int moistureMaxima[numberOfPlants] = {195, 682, 750, 950};

// Servo holding the indicator needle.
Servo indicator;
int sensorValue = 0; // value read from the Soil Moisture
void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);
  pinMode(waterSensorPin, INPUT);
  pinMode(buttonPin, INPUT);
  for (int ledNo = 0; ledNo < numberOfPlants; ledNo++) {
    pinMode(ledPins[ledNo], OUTPUT);
  }
  indicator.attach(servoPin);
}

void loop() {
  // Which plant are we currently monitoring?
  static int whichPlant = noPlant;
  sensorValue = analogRead(waterSensorPin);// read the analog in value:

  // Switch to next plant on button press.
  if (digitalRead(buttonPin) == HIGH) {
    if (whichPlant != noPlant) {
      digitalWrite(ledPins[whichPlant], LOW);  // turn off previous LED
    }
    ++whichPlant;
    if (whichPlant == numberOfPlants) {
      whichPlant = noPlant;
    } else {
      digitalWrite(ledPins[whichPlant], HIGH);  // turn on current LED
    }

  }
  if (whichPlant == noPlant) {
    digitalWrite(10, LOW);  // turn off previous LED
    digitalWrite(12, LOW);  // turn off previous LED
    lcd.clear();
    lcd.noDisplay();
    lcd.setRGB(zeroR, zeroG, zeroB);

  }
    if (whichPlant == 3) {

      digitalWrite(10, HIGH);  // turn off previous LED
      digitalWrite(12, HIGH);  // turn off previous LED
      lcd.setRGB(plant4R, plant4G, plant4B);
      lcd.clear();
      lcd.display();
      lcd.print("Swamp Plant");// print the results to the LCD Display:
      sensorValue = map(sensorValue, 0, 950, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
      delay(500);  // crude debouncing
    }
    if (whichPlant == 2) {
      lcd.setRGB(plant3R, plant3G, plant3B);
      lcd.clear();
      lcd.display();
      lcd.print("Orchid");// print the results to the LCD Display:
      sensorValue = map(sensorValue, 0, 750, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }
    if (whichPlant == 1) {
      lcd.setRGB(plant2R, plant2G, plant2B);
      lcd.clear();
      lcd.display();
      lcd.print("Sunflower");// print the results to the LCD Display:
      sensorValue = map(sensorValue, 0, 682, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }
    if (whichPlant == 0) {
      lcd.setRGB(plant1R, plant1G, plant1B);
      lcd.clear();
      lcd.display();
      lcd.print("Cactus");// print the results to the LCD Display:
      sensorValue = map(sensorValue, 0, 195, 0, 100);
      lcd.setCursor(0, 1);
      lcd.print(sensorValue);
      lcd.print("% Enough water");
      Serial.println(sensorValue);
    }

  // Report the moisture level of this plant.
  if (whichPlant != noPlant) {
    int sensorValue = analogRead(waterSensorPin);
    int position = map(sensorValue,
                       moistureMinima[whichPlant], moistureMaxima[whichPlant], 180, 0);
    indicator.write(constrain(position, 0, 180));
    Serial.println(sensorValue);
    delay(500);

  }
  // added 14-02 to make sure servo pointer goes back to start after reading last reading from waterSensor
  if (whichPlant == noPlant) {
    int sensorValue = analogRead(waterSensorPin);
    int position = map(sensorValue,
                       moistureMinima[whichPlant], moistureMaxima[whichPlant], 180, 0);
    indicator.write(constrain(position, 180, 180));
    delay(500);

  }

  //gemaakt door Sinan van Noppen
}

what does contentiously mean? ... do you mean continuously or continually?

you could use an array as a lookup table for data ... the four if (whichPlant == x) { could be replaced by one code block with data being retrieved from a lookup table plant1R, plant1G, plant1B, "Orchid", 195, "% Enough water"

look at this https://www.arduino.cc/en/Tutorial/Debounce ...... put the ++whichPlant; at the line in the tutorial  where the LED is toggled

the code starting at if (whichPlant == 3) { should not be inside of the if (digitalRead(buttonPin) == HIGH) { block ...................your code should check the button at the begining of the loop() block and increment the whichPlant variable if required ......... the subsequent code should always run and it should react to the value of whichPlant only ... it should not react to any button presses, or be prevented from running by any button state

you need to make some helper functions to cut down on the repetition and make the code easier to maintain. it looks like one to handle the plant could accept parameters of a string label and an upper bound for the map. another function should be the only way print to the lcd, from one place, i call it render(). you want the loop function to be short and to mainly call sub-routines to handle the details.

@jsotola hahah yes continuously, sorry

@dandavis Okay and how do I do that then? I'm not a programmer btw nor do I know any programming language, this is all new to me  :(

@jsotola okay so I see what you're saying about arrays the only problem is I have no clue how?? I have tried tinkering with it for hours but nevertheless I don't know.  As what you said I tried making a array int Orchid [] {plant3R, plant3G, plant3B, "Orchid", 750, "% Enough water"}; but if this is correct and then how to acces it? So the code works fine now it does what I want to do, but how I make it so it's cleaner with arrays and lookup tables I have no clue. I added updated code in EDIT.

no, an array like moistureMinima[] .... domething like this for the names plantNames[4] =  {"Cactus", "Sunflower","Orchid","Swamp Plant"}  .... use multiple arrays


text:
Reading PROGMEM results in an incorrect hex value
I'm sure I'm doing something stupid here, but the code below is supposed to write the test hex values to a I2C EEPROM, however when I attempt to read the EEPROM it has the wrong values.  Directly calling something like Wire.write(0xab) will write the 0xab as expected, so I know the EEPROM is being written to properly, just something seems to be getting lost in translation when writing test[counter++]
.
#include <Wire.h>

const byte test[] PROGMEM = {
  0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80,
  0x7f, 0x7f, 0x81, 0x7f, 0x7e, 0x81, 0x80, 0x7f, 0x7f, 0x7f, 0x80, 0x7e,
  0x7e, 0x81, 0x7e, 0x7c, 0x7f, 0x7f, 0x7d, 0x7c, 0x7f, 0x7f, 0x80, 0x7e
};

unsigned int test_len = 36;

#define EEPROM_ADR 0x50

void setup()
{
  Wire.begin();

  int counter = 0;

  Wire.beginTransmission(EEPROM_ADR);

  Wire.write((int)(0x0 >> 8)); //msb
  Wire.write((int)(0x0 & 0xFF)); //lsb

  while (counter < test_len)
  {
    Wire.write(test[counter++]); //using page buffering to write the entire array
  }

  Wire.endTransmission();
}

The results look something like: 0x00 0x00 0x08 0x00 0x00 0x00 0x01 etc..

remove PROGMEM to test. you don't use the pgm_read function to read PROGMEM

what is the purpose of the first two Wire.write  commands?  .... i think that they both write a zero ... is something missing from those two lines?

Juraj, you're right, but in my real code the array is quite large so it needs to be in PROGMEM, is there something I'm missing about that memory location?

That was it, it works.

you learned how to troubleshoot. next time create a minimal sketch. now please delete the question.

To obtain the size of your array you can use sizeof test / sizeof test[0]. This works with any data type of an array's elements.

I needed to either remove PROGMEM from the array or use pgm_read_byte to read the array.


text:
Part identification
This may be a dumb question but i would like to know what this part is. Anyone who knows?

Create a full picture (who knows what's behind your fingers), dimensions, any textual identification, where and in what device you found it (and what brand, model).

maybe something like that?
https://www.aliexpress.com/item/32847035065.html

We cannot see anything on that image. About 99% of that image is not showing the part

Maybe something like this (just kidding): https://nl.123rf.com/photo_73468723_rustieke-houten-plank-met-nagels-geïsoleerde-bruine-plank-.html

it looks like an index finger and the middle finger ... the item taking up most of the image is a wall

This looks like something out of an Arduino n-part “sensor kit”. It’s hard to tell because the quality of the image is not very good.
My guess is, this is an analog temperature sensor, like in this link, part number 18. You can also find an example sketch there.


text:
How to modify this code to use serial event to act after carriage return?
In part of a code used with UNO, I want to send number A and number B at once as A,B to the Arduino board if there is carriage return. So at the moment in HyperTerminal when I type: 100,0.5 the Arduino board immediately reacts x becomes 100 and n becomes 0.5. Following parts are related to reading with serial event:
void loop() {

      if (stringComplete){

      delay(1000);
      Mwrite(level);
      sendFrequency(n);
      delay(100);

      stringComplete = false;

   }
}

and in serial event:
void serialEvent() {

     while (Serial.available()) {

     slevel  = Serial.readStringUntil(',');
     Serial.read(); //next character is comma, so skip it using this
     x = Serial.readStringUntil(',');

     level = slevel.toInt();
     n = x.toDouble();
     stringComplete = true;
  }
}

But what I want to do is, I want the board only read the serial data only if I hit carriage return. So I should type 100,1 and then I should also hit carriage return for Arduino to react to the serial data.
How can this code be modified to achieve that?

Forget serialEvent(). It's something Arduino should never have included in the API. It's an idiotic function that has no purpose in reality. Putting the content of serialEvent() in loop() is exactly the same (and often far more convenient).

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

The SerialMonitor does not send anything until you press "Send". It's a good idea to choose newline as additional delimiter character when sending. In addition to Majenko's  readline:  There's a strtok function you might want to use

set the terminal to send on Enter, not every character. btw. readStringUntill removes the terminal character from receive buffer. and shouldn't your second readStringUntil read until '\n'?

@Majenko, no it's not idiotic, it's just misunderstood. I'll admit it has limited use-cases, but it can be a big help. For instance, it helped a ton when designing my RC airplane library

The concept may have merit, but the implementation is idiotic. Now if they'd hooked it into the RX interrupt then it may have been useful. As it is, it's idiotic. And I stand by that word.

There are multiple ways you can solve it. The easiest way to do it is by just adding one more line in your code.
static bool stringComplete = false;
String x;
String slevel;
static int level;
static int n;

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

void loop()
{
  if (stringComplete)
  {
    Serial.println(level);
    Serial.println(n);
    stringComplete = false;
  }
}

void serialEvent()
{
  while(Serial.available())
  {
    slevel  = Serial.readStringUntil(',');

    //Serial.read(); // <-- You don't need this line. readStringUntil() will read ','

    x = Serial.readStringUntil(',');

    level = slevel.toInt();
    n = x.toDouble();
    Serial.readStringUntil('\r'); // <--------- Add this line
    stringComplete = true;
  }
}

But this is not probably the right way to do it. First, serialEvent() executes in between loop() i.e. this is what it looks like:
while(1)
{
    loop();
    serialEvent();
}

So, it is not like that the function will get called during a serial event. It just gets executed right after loop(). Also readStringUntil() has a timeout (default: 1s). So if your 'until' character doesn't show up within one second of the function call, it will return with whatever it has. To test this, just type one character on your HyperTerminal and wait at least for a second, and see the output.
Ideally, this is how you should handle the serial's incoming byte:

Check if there is serial byte available to read
If there is, read one byte and save it in a buffer/string. (I'm not really a fan of String variables, but in the example, I will use String because you were using a String)
If the byte you just read is delimiter (e.g. CR or '\r'), indicate the main loop that string is complete.
In the main loop parse the whole string.

So this is how the code looks like with above-mentioned points:
static bool stringComplete = false;
String x;
String slevel;
static int level;
static int n;
String rxString = "";

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

void loop()
{
  if (stringComplete)
  {
    // Parse the rxString
    int index1 = rxString.indexOf(',');             // finds location of first ,
    slevel = rxString.substring(0, index1);         // captures first data String
    int index2 = rxString.indexOf(',', index1 + 1); //finds location of second ,
    x = rxString.substring(index1 + 1, index2);     //captures second data String

    level = slevel.toInt();
    n = x.toDouble();

    Serial.println(level);
    Serial.println(n);

    // Reset the string
    rxString = "";
    stringComplete = false;
  }
}

void serialEvent()
{
  while(Serial.available())
  {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the rxString:
    rxString += inChar;
    // if the incoming character is a carriage return, indicate main loop
    if (inChar == '\r')
    {
      stringComplete = true;
    }
  }
}


text:
DHT11 analog or digital?
I saw some projects with DHT11, some connect it with analog pin, others connect with digital pin.
Is there any difference / advantage connecting to the analog?

The DHT11 is a digital component with its own digital communication protocol.
Analog pins can be used for either analog input or digital input and output.
You can use a digital device like the DHT11 on any pin, whether it is labelled analog or digital (except on a couple of boards which have a few analog-only pins).


text:
MPU6050 stuck on same values while getting the angle as output
I am trying get the rotation value from MPU6050. I am using an Arduino Uno board.
My connections are:
MPU6050  Arduino

VCC    ->  5V
GND    ->  GND
SCL    ->  A5
SDA    ->  A4
INT    ->  2

The code I am using is:
#include <MPU6050_tockn.h>

#include <Wire.h>

MPU6050 mpu6050(Wire);

void setup() {

  Serial.begin(9600);

  Wire.begin();

  mpu6050.begin();

  mpu6050.calcGyroOffsets(true);

}

void loop() {

  mpu6050.update();

  Serial.print("angleX : ");

  Serial.print(mpu6050.getAngleX());

  Serial.print("\tangleY : ");

  Serial.print(mpu6050.getAngleY());

  Serial.print("\tangleZ : ");

  Serial.println(mpu6050.getAngleZ());

  delay(4000);

}

On my serial monitor I am always getting -35.26, 35.26, -0.0 values. What should I do?


text:
Why does my ATtiny85 blink program only work with 4 out of the 16 registers?
The following blink program runs fine on my Attiny85 SparkFun Tiny AVR programmer board. It produces 5 short blinks and then stops.
It also works fine when I change r16 to any one of the registers r17, r21 or r29. But trying with any other register gives either no blink at all (r19, r20, r23, r25, r26, r27, r28, r31) or indefinite blinks (r18, r22, r24, r30).
Can anyone explain?
int ledPin = 0;

void setup() {

  pinMode(ledPin, OUTPUT);

  asm("ldi r16, 5");
  asm("blink:");
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
  asm("dec r16");
  asm("brge blink");
}

void loop() {
}

Why are you trying to mix assembly in there like that without first knowing what registers are already being used by the program for other purposes? Either use C or use assembly. Don't mix them like that.

I usually do not mix like this, but inserted the blink part for  a debugging reason. Why I use inline assembly is to speed up an inner loop.

Solved it myself! The high-level command "delay(500)" destroys the register contents. Saving the register (using push/pop) while doing delay() solves this issue. (Btw, is should be "brpl" and not "brge".)

As you discovered, calling a function may clobber some registers. To be precise, the avr-gcc documentation says:

Call-Used Registers
The call-used or call-clobbered general purpose registers (GPRs) are registers that might be destroyed (clobbered) by a function call.
R18–R27, R30, R31
These GPRs are call clobbered. An ordinary function may use them without restoring the contents. Interrupt service routines (ISRs) must save and restore each register they use.
Call-Saved Registers
R2–R17, R28, R29
The remaining GPRs are call-saved, i.e. a function that uses such a registers must restore its original content. This applies even if the register is used to pass a function argument.

Now, an interesting detail here is that according to the documentation, one would expect R28 to work. Maybe that's not clobbered by the called procedure, but by your local procedure (mixing assembly and C in nontrivial amounts is a difficult
task for precisely this reason).


text:
I need to happen a process between 2 given times in Arduino
In my project i have a function which i only need to execute if the current time is between given 2 times. Note that the time is fetched from RTC so its 24hr. For example if current time is 23:00,start time is 20:00 and end time is 5:00 the function must execute and not execute otherwise.
if((fromhour>=now.hour() && fromminute>=now.minute()) || (tohour>=now.hour() && tominute>=now.minute()))
{
     //Call function
}

I tried this code but not working as expected. please give a solution for this problem.

convert now.time() hh, mm, ss into three separate bytes and do the comparison that way

How to compare. I need the if statement. Can you give me the code.


text:
not able to figure out what is wrong with my nodemcu code
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>

//Firebase settings
#define FIREBASE_HOST "..........firebaseio.com/"     //cant share
#define FIREBASE_AUTH "..............."               //cant share

//Wi-Fi settings
#define WIFI_SSID "kello"
#define WIFI_PASSWORD "8888"

//Define trigger and echo digital pins
const int trigPin = 4;
const int echoPin = 3;

// The amount of time the ultrassonic wave will be travelling for
long duration = 0;
// Define the distance variable
double distance = 0;

void setup()
{
     Serial.begin(9600);
    // Connect to Wi-Fi
    Serial.print("Wi-Fi...");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    Serial.print("Connecting...");
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
    }
    Serial.println();
    Serial.print("Connected to: ");
    Serial.println(WiFi.localIP());

    Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);

    // Ultrasonic sensor, set echo as Input and trigger as Output
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);

}

void loop()
{

    getDistance();
    // Prints the distance value to the serial monitor
    Serial.print("Distance: ");
    Serial.println(distance);

    delay(500);
}

void getDistance()
{
    // Clear trigPin
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);

    // trigPin HIGH por 10ms
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    //Reads echoPin, returns the travel time of the sound wave in ms
    duration = pulseIn(echoPin, HIGH);

    // Calculating the distance, in centimeters, using the formula described in the first section.
    distance = duration * 0.034 / 2;

    // Sends the distance value to Firebase
    Firebase.setFloat("distance", distance);

}

I am a computer graduate so i do not have much knowledge about nodemcu. I saw some documentations about nodemcu. I want to show the data obtained by the ultrasonic distance sensor in the realtime database of firebase. But i am not able to figure out why i am not able to get output of serial.println(distance) in the com5 window even though the code compiles successfully .
This is what i get when running the program
Executable segment sizes:

IROM   : 330560          - code in flash         (default or ICACHE_FLASH_ATTR)

IRAM   : 27760   / 32768 - code in IRAM          (ICACHE_RAM_ATTR, ISRs...)

DATA   : 1408  )         - initialized variables (global, static) in RAM/HEAP

RODATA : 2044  ) / 81920 - constants             (global, static) in RAM/HEAP

BSS    : 25160 )         - zeroed variables      (global, static) in RAM/HEAP

Sketch uses 361772 bytes (34%) of program storage space. Maximum is 1044464 bytes.
Global variables use 28612 bytes (34%) of dynamic memory, leaving 53308 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port COM5
Connecting....
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: ec:fa:bc:c1:44:d2
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 365920 bytes to 264395...

Writing at 0x00000000... (5 %)
Writing at 0x00004000... (11 %)
Writing at 0x00008000... (17 %)
Writing at 0x0000c000... (23 %)
Writing at 0x00010000... (29 %)
Writing at 0x00014000... (35 %)
Writing at 0x00018000... (41 %)
Writing at 0x0001c000... (47 %)
Writing at 0x00020000... (52 %)
Writing at 0x00024000... (58 %)
Writing at 0x00028000... (64 %)
Writing at 0x0002c000... (70 %)
Writing at 0x00030000... (76 %)
Writing at 0x00034000... (82 %)
Writing at 0x00038000... (88 %)
Writing at 0x0003c000... (94 %)
Writing at 0x00040000... (100 %)
Wrote 365920 bytes (264395 compressed) at 0x00000000 in 23.4 seconds (effective 125.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Is the ultrasonic sensor not getting enough power supply as nodemcu is connected to my laptop?
Please help me out and let me know if more information is required.

https://electronics.stackexchange.com/questions/402066/esp8266-free-gpios-for-relay-switching/404845#404845

Your echoPin Is defined as 3. GPIO3 of the NodeMCU is also the “RX” pin needed for serial communication to the host. This might explain why you don’t see any output. You should change it to a different pin (for example pin 5 / D1 is a safe choice).
Each pin on the NodeMCU has a “GPIO” number (which is just the pin number as defined by the ESP8266 architecture) and a corresponding “Dx” designation (which is usually marked on the NodeMCU board).
Which GPIO pin corresponds to which which “D” pin is shown in pinout diagrams, like the one here. Scroll to the NodeMCU 12-E pinout.
Some of the safest pins to use are:

Pin 5 (D1)
Pin 4 (D2)
Pin 12 (D6)
Pin 13 (D7)
Pin 14 (D5)

Some of the other pins could also be used, but have some restrictions, as you can see on the page I linked to.
Note that pins 12-14 are used for SPI and pins 4 and 5 are (normally) used for (software) I2C. If you want to control hardware that uses these protocols, these are the default pins it uses.