text:
Serial not declared in this scope, newbie mistake most likely
Ok, newguy with a little VBA coding experience going to pull hair out soon. It is probably a simple thing I have missed but I would like someone to point out where I went wrong. I modified a sketch that used an lcd to use the serial monitor instead but I sometimes run into this "not declared in this scope" issue. Doing something wrong, please point me in the correct direction.
#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;
DateTime now;
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void showDate(void);
void showTime(void);
void showDay(void);

void showDate()
{
  serial.print(now.day());
  serial.print('/');
  serial.print(now.month());
  serial.print('/');
  serial.print(now.year());
}

void showDay()
{
  serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
}

void showTime()
{
  serial.print("Time:");
  serial.print(now.hour());
  serial.print(':');
  serial.print(now.minute());
  serial.print(':');
  serial.print(now.second());
  serial.print("    ");
}

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

  serial.println("working....")
  //wire.begin();
  //delay(2000);
  if (! rtc.begin())
  {
    Serial.println("Couldn't find RTC Module");
    while (1);
  }

  if (rtc.lostPower())
  {
    Serial.println("RTC lost power, lets set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop ()
{
  now = rtc.now();
  showDate();
  showDay();
  showTime();
}

Case matters in C/C++. You should write Serial rather than serial.

OMG, I will not live that down!!!

Sorry, I will be more careful with that. I am used to VBA where if you @@$ up syntax it highlights it. Thanks for your quick answer. Hiding head now, lol

As a nebie I also noticed that when syntax is valid the color of the code is red/orange. Are functions highlighted in the IDE?

Built-in functions appear to be highlighted in orange, reserved words in blue-ish. Strings in Green-ish? Pretty sure it doesn't parse your code to highlight specific to your project.


text:
Integer corruption
I use a sensor to measure the temperature. This is returned as float. I feed this float using typecasting (int) to a blink function. This works fine.
But the next is step is using this same unchanged integer in a struct and send it over 433MHz using RadioHead.
Here the integer is no longer an integer and it never gets sent.
When I hard code the sensor measurement value, it works. When I hard code the value in the struct it works. When I hard code the value anywhere it works.
My assumption is: when the blink works it must be an integer. When sending a hard coded integer works it must also send the measured value confirmed to be an integer. What am I missing here?
The chip is an ATtiny85
The sensor is a DS18B20
TinyHead, my light RadioHead version: https://gitlab.com/thijsvanulden/TinyHead
This is the Logic Analyzer view of what happens measured on the Data pin of the 433MHz transmitter. So something is happening at least. I can't find an Analyzer 'plugin' to translate the message coded in RadioHead, it's not Manchester encoding as it seems.

Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [========  ]  75.8% (used 388 bytes from 512 bytes)
PROGRAM: [========= ]  86.4% (used 7080 bytes from 8192 bytes)

#include <Arduino.h>
#include <util/delay.h>
#include <OneWire.h>
#include <RH_ASK.h>
#include <DallasTemperature.h>

#define TICKLE_ID 0

#define ONE_WIRE_BUS 2

#define RADIOHEAD_BAUD 2000
#define RADIOHEAD_TX_PIN 1
#define RADIOHEAD_RX_PIN -1

#define LEDPIN 0

struct tickle {
  uint16_t id = TICKLE_ID;
  uint16_t value1;
  uint16_t value2;
};

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RH_ASK driver(RADIOHEAD_BAUD, RADIOHEAD_RX_PIN, RADIOHEAD_TX_PIN);

void blink(int repeat) {
  for (int i = 0; i < repeat; i++) {
    digitalWrite(LEDPIN, HIGH);
    _delay_ms(100);
    digitalWrite(LEDPIN, LOW);
    _delay_ms(100);
  }
}

void senddata(float temperatuur) {
  blink((int) temperatuur); // this always works
  struct tickle package; // make a Tickle package
  package.id = TICKLE_ID; // hard-coded device ID
  package.value1 = 0; // any positive int up to 2^16
  package.value2 = temperatuur * 100; // any positive int up to 2^16
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

void setup() {
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, HIGH);
  sensors.begin();
  driver.init();
  _delay_ms(100);
  digitalWrite(LEDPIN, LOW);
}

void loop() {
  sensors.requestTemperatures();
  _delay_ms(100);
  senddata(sensors.getTempCByIndex(0)); // hard coded 17.07 works
  _delay_ms(10000);
}

Changes made as suggested by @Jot
void senddata(float temperatuur) {
  temperatuur = (uint16_t) temperatuur;
  blink(temperatuur);
  struct tickle package; // make a Tickle package
  package.id = (uint16_t) TICKLE_ID; // hard-coded device ID
  package.value1 = (uint16_t) 0; // any positive int up to 2^16
  package.value2 = (uint16_t) 100; // any positive int up to 2^16

  blink(sizeof(package));
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

Working code, the end result
You may need to skip the Powernap code, it's a sleep library for ATtiny85. And I use the TinyHead library for 433MHz. The OneWire interaction with the sensors is 'borrowed' from http://www.nerdkits.com/forum/thread/2849/ so please send the beer and kudo's there.
#include <Arduino.h>
#include <util/delay.h>
#include <OneWire.h>
#include <RH_ASK.h>
#include <powernap.h>

#define TICKLE_ID 0
//
#define ONE_WIRE_BUS 2
//
#define RADIOHEAD_BAUD 2000
#define RADIOHEAD_TX_PIN 1
#define RADIOHEAD_RX_PIN -1

#define LEDPIN 0

struct tickle {
  uint16_t id = TICKLE_ID;
  uint16_t value1;
  uint16_t value2;
};

Napper napper;
OneWire TemperatureSensor(2);
RH_ASK driver(RADIOHEAD_BAUD, RADIOHEAD_RX_PIN, RADIOHEAD_TX_PIN);

void blink(int repeat) {
  for (int i = 0; i < repeat; i++) {
    digitalWrite(LEDPIN, HIGH);
    napper.delay(100);
    digitalWrite(LEDPIN, LOW);
    napper.delay(100);
  }
}

void senddata(float temperatuur) {
  blink((int) temperatuur);
  struct tickle package; // make a Tickle package
  package.id = TICKLE_ID; // hard-coded device ID
  package.value1 = 0; // any positive int up to 2^16
  package.value2 = temperatuur * 100; // any positive int up to 2^16

  blink(sizeof(package));
  driver.send((uint8_t *)&package, sizeof(package));
  driver.waitPacketSent(); // wait for it ~Barney
}

void setup() {
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, HIGH);
  driver.init();
  napper.setup();
  napper.delay(100);
  digitalWrite(LEDPIN, LOW);
}

void loop() {
  byte i;
  byte data[12];
  int16_t raw;
  float celsius, fahrenheit;

  TemperatureSensor.reset();       // reset one wire buss
  TemperatureSensor.skip();        // select only device
  TemperatureSensor.write(0x44);   // start conversion

  delay(1000);                     // wait for the conversion

  TemperatureSensor.reset();
  TemperatureSensor.skip();
  TemperatureSensor.write(0xBE);   // Read Scratchpad
  for ( i = 0; i < 9; i++) {       // 9 bytes
    data[i] = TemperatureSensor.read();
  }

  // Convert the data to actual temperature
  raw = (data[1] << 8) | data[0];
  celsius = (float)raw / 16.0;
  napper.delay(100);
  senddata(celsius);
  napper.napminutes(1);
}

Which arduino board do you use? The OneWire and DallasTemperature require some memory, but the RadioHead requires a lot of memory.

@Jot - how is that relevant? if senddata(17.07); works as intended, but senddata(sensors.getTempCByIndex(0)); does not?

what sensor are you using? .... what format is the returned data?

Is it possible you think you are sending three bytes of data while you might actually be sending six bytes of data.

@Thijs, still using the attiny85? or is it a secret and you don't you want to tell us which arduino board you use? When you use a non-standard arduino board, then I would like to know which core you use. Perhaps that is a secret as well? There are issues and notes about many problem with the attiny85 and RadioHead. Have you read: "Caution: we have not had good success building RH_ASK sketches for ATTiny 85" on this page: https://www.airspayce.com/mikem/arduino/RadioHead/ The RadioHead uses a lot more memory than the old VirtualWire. I would not even recommend the RadioHead for an Arduino Uno.

What do you mean by “the integer is no longer an integer and it never gets sent”? What makes you believe an integer can be anything but an integer? What are the exact symptoms you observe?

Yes, I use an ATtiny85. It is the Dallas sensor DS18B20. The returned format is float. @Jot sry forgot to mention I use the ATtiny85. I have 17 sensors running with this chip and using TinyHead, my light version of RadioHead, no problems there. VirtualWire does not provide the same functionality and is deprecated for years with the developer referring to RadioHead.
The exact symptoms are that the RadioHead library does not send out the message. In depth debugging is really hard with an ATtiny85 so can't really tell you more at the moment but I'm open to ideas.
@st2000 please elaborate?

@st2000 I changed my code so the LED blinks the package size and sizeof(package) returns 6.

...yes, this is because your structure is made of 3 uint16_t values.  Then you force the code to consider it as uint8_t values.  Of which there is enough memory set aside for 6 such values.  I was wondering if this was what you were expecting to send?  Or if this was why you do not think you are sending the correct data.

...also, as other's here point out, the Arduino paradigm has been ported to many many different processors.  And some of the ports are not 100% functional.  In fact, it can easily be said that not 100% of all Arduino programs run on 100% of all "so called" Arduino platforms.

Please also add a link in your question to TinyHead. I can't see the problem. Therefor you have to be able to get closer to the problem with other output. Can you add a serial port, a display, or a led? Perhaps you can blink a led 17 times for 17 degrees in the function senddata and check if you see any difference for a constant or the ds18b20. By the way, I have stripped down the RadioHead for myself, saving a lot of ram. That makes it possible to use it with an arduino uno. I doubt if the TinyHead for a attiny85 is tiny enough so it can still use the ds18b20 libraries.

@st2000 where do I force the code to consider it uint8? What would be the alternative?

@Jot I’ve used an LED to signal the temparature and its read fine. I also used it to signal the package size for the transmission and it’s 6 bytes. I will try to connect my logic analyzer later. Yes is all works with a constant. Thats the problem, it always works with any integer unless the integer comes from the sensor, even when I verify this interger is fine by blinking the LED.

@Thijs I think I did not read it very well and was rude, my apologies. Can you do a test: fool the compiler to make it think that getTempCByIndex is used, but send a constant. In the function senddata: convert it: uint16_t t = temperature; get rid of it: t /= 10000; add a constant: t += 1789; fill the package: package.value2 = t;. Linking the getTempCByIndex function into the binary might be too much for the ram usage.

@Jot no problem. I've made the changes and nothing is transmitted but I do see the right temperature signaled by the blink function. On the logic analyzer there is a signal again, but I still cant decode it.

I'll try to use another more light library or write my own oneWire stuff so I can free up some memory.

Casting values is like telling the compiler "don't mind what these memory locations were, now I want you to treat them differently".  So, you used 6 bytes of memory to store 3 uint16_t values.  Then you told the compiler to look at the 6 bytes of memory as if they were uint8_t values.   You further cemented your intentions by specifying the "size" of the values.  That is, the size of function returned that you had used 6 bytes of memory for the storage of the 3 uint16_t variables or, as you casted them, 6 uint8_t variables.

@st2000 I still do not know where I tell the compiler to look at the 6 bytes of memory as if they are uint8_t, could you please specify the exact line where I do this? As far as I know I just declare a variable to be a 16 bit long integer and never change that.

In this line:   driver.send((uint8_t *)&package, sizeof(package));

I can’t believe I missed that, not sure what happens for the sensors that work fine.. at the receiving end the 6 int8’s are interpreted as 3 int16’s again

It works when I do not use a heavy DallasTemperature library but directly use OneWire as seen here: http://www.nerdkits.com/forum/thread/2849/, so I think it was indeed the memory issue @Jot mentioned..

source: Stack Exchange

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

sort: votes


text:
Failsafe Arduino
I want to read an RFID tag using an Arduino, which controls some relais. This is easy.
For me the more complex part is to build it fault-tolerant. So I thought I could use the watchdog. The tricky part is, my relais module should keep a certain state (change of state is rare), no matter what happens to the Arduino.
My first thought was to put some condensators to the relais. Calculate the RC component so it can last the watchdog timeout plus booting up.
Now there is the problem, that the relais module is keeping its state while booting. I guess I can't use a pull up/down resistor, since the state of the relais can be low or high at random.
My second thought was using a latch relay. But this has the disadvantage, that it probably can hide problems. For example if the arduino died, and the latch relay holds a certain state, it masks the problem. In that case it's not possible to notice a faulty Arduino.

Those are the reasons I tend to think condensators are better?
Are those ideas feasible? Are there easier ways to accomplish this?
Are there more problems to think about?

(I was already reading about millis at gammon's page. Apparently it's not a problem after all.)

Please explain why and where you would need a pull up/down resistor.

you are contradicting yourself in your statements ......... relais module should keep a certain state (change of state is rare), no matter what happens to the arduino ........ and if the arduino died, and the latch relay holds a certain state, it masks the problem

It is impossible to solve. You need to be able to detect all problems for everything. When the wire of the rfid coil breaks or shorcuts, how can you detect that? A smoke detector can detect smoke and a low battery voltage. That's all. To make it reliable, a good quality smoke detector is required and it should be tested every month (some manuals say: every week). You need therefor the best quality hardware and software to start with.

@jsotola: this is due to unclear requirements. I wasn't sure about them. After thinking a bit more: I think I want to keep the state only for a certain amount of time. Enough time for the arduino to recover. Or else go into default state, where nothing happens, and I can see a problem. If the state is kept infinite, then I don't see the problem easily.

@jot: I think the only requirement I have: If the rfid reader tells me he read a certain tag, it should be true. if he fails, nothing is working, and I can detect the problem. I think with a timed latch I can go to a default state, where I shut down the relais module. So I hope I should be fine.

Consider constraining your design with clear requirements.  As it is highly unlikely any design can protect its self for all situations.

my relais module should keep a certain state (change of state is rare), no matter what happens to the arduino

Consider latching relays where there is a set coil and a reset coil.  Such as  this one.  Such a device does not need to be continuously powered.  Only pulsed to set and a pulsed to reset.

So I thought I could use the watchdog.

Watchdog timers are fine if your program can get stuck waiting for an event that may never happen.  Like waiting to read the data from and RFID chip.  If you think this might happen, then add the watchdog timer to your design.

Now there is the problem, that the relais module is keeping its state while booting.

Most embedded processors with bi-directional GPIO pins force those pins to be inputs when booting up.  This appears as high impedance to the outside world.  Consider using pull ups or pull downs on these pins to prevent them from floating to a state which may change the relays during booting of the processor.

Yes you're totaly right. My requirements are not clear. Even I am not sure about them. Good point. I was thinking about a timed latch. If I go into default state, nothing happens and I can detect a problem. If there is a state other than default, I want to be sure it's the proper one.

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


text:
Analog output gives a close range of values
I try to get a good range of values from VMA309 sound sensor.
However, when I connect it properly it gives me a range of values  +/-5 like below. The documentation says it should give numbers between 0 and 1024.
I turned the potentiometer both sides all the way and that only changed the number, but it keeps gives number in a range of 5 numbers:
An example:
626
623
624
624
624
624
623
624
624

My code:
int sensorPin = A5;
int sensorValue = 0;
void setup ()

{
  Serial.begin (9600)  ;
}

void loop()
{
  sensorValue = analogRead(sensorPin);
  delay (500);
  Serial.println (sensorValue, DEC);
}

What am I doing wrong here?
An image of the wires:
I also tried the wiring directly without a breadboard. But that gave the same results.

I used the code as given from the VMA 309 documentation.

The original maker could be velleman: https://www.velleman.eu/products/view/?id=435532 They also have a schematic: https://www.velleman.eu/downloads/29/infosheets/vma309_scheme.pdf The analog output is the signal directly from the microphone output. That is a silly circuit. When the wrong microphone is used or when the microphone is 180 degrees rotated and soldered on the board, it won't work. You are doing probably nothing wrong, but to be sure you can show the code that you use and a photo of the wiring. Have you tried blowing into the microphone?

Thanks for your reply, yes i tried that. That resulted in a range difference of about 30 at maximum. I added the code aswell as a picture of the arduino with the sensor.

I don't understand from picture if sensor is powered by 5V or 3.3V. If it's powered from 3.3V , you are wrong.

I tried 3.3 and 5V the back of the product says that both should work. At both voltages i get the same results, only different values

Give a try to exclude issue from Arduino, you run code for all analog pins (A0, A1 etc...) and check if result is the same..

Try to understand first how the ADC  module works. Test it with a simple potentiometer and learn how the values change according to the voltage divider from the potentiometer. Also, the title from your question is misleading since 'analog output' in the Arduino world refers to writing PWM values through a pin from the Arduino using the analogWrite function. In your case, the problem involves an analog signal fed to an analog 'input' pin

I have had a smimilar issue extracting the data to ardino module.
-with 5V power supply the counts were varying from 1009~1023.
-with 3.3V power supply the counts were in the range of 610~640
I connected an scope and found out the MIC module gives an AC outputput of 340mV max sitting over DC signal of 3.3(at 5V supply) and 1.7(at 3.3Vsupply).
On thing was very clear that However the MIC is giving and out put, we need to consider the analoag ref. voltage, for an ADC the input can never be higher than Vref. i.e. 2.56V.So 5V suppy is not going to work. Also if 1.1 Vref is selected the ADC  will remain saturaed alaways at 1023 and won't work.
Also consider a need to subtruct and offset of 1.7V while working with 3.3V supply.
As a summary,
1- Set Vref of Arduino ADC module to 2.56V
2- Use 3.3V supply for VMA309 sound sensor
3- Consider a DC offset of 640 counts approx and the actual voice signal will be sitting on this offset value. May need to decouple in a software code.
4- Set a VMA309 sound sensor module threshold at a reasonable point to capture the full spectrum of voice.
5- The delay(ms) in a code shall be removed to get max capture rate or Set an ADC in a free running mode to caputure at max sampling rate(15KSPS for ATmega2560).

Arduino is a lot of fun, but you better stay away from such modules.
The module is a resistor and a electret microphone. There is also a comparator for the digital output. When you have an electret microphone, and add a resistor of 4k7 or 10k, then you have the same.
The signal from the microphone is not amplified and the Arduino only gets the analog value of the audio. The module does not measure how loud the audio is.
I think Velleman makes them: www.velleman.eu/products/view/?id=435532
They are so kind to have a schematic available: vma309_scheme.pdf
Can you move on and use the Arduino for something else?
This module with this microphone is probably not going to work.
If you want to measure the sound level, then perhaps you can make a circuit yourself or buy a better module.
The "Sound Pressure" is how loud audio is.
The most used standard is called "Sound Pressure Level" or "SPL" and is measured in dB (deciBell).


text:
How to convert jpeg byte stream into jpeg image and display on 1.8 inch TFT display
I have an ESP32 having a cam and it is transmitting compressed JPEG stream.

TTGO T-Journal ESP32
Camera Development Board
OV2640
SMA WiFi
3dbi Antenna
0.91 OLED Camera Board

I have an ESP32 having a 1.8 inch TFT screen and a SD card slot which act as receiver.

ESP32 TS V1.2
MPU9250
1.8 Inch TFT
Bluetooth
Wifi
MicroSD Card Slot
Speakers Module

On Chrome browser, I get a display of the JPEG images as a continuous image after image (video).
I can see the incoming compressed JPEG stream and i print it on serial monitor .
But I need to decode/ decompress the JPEGstream at receiving end and paint pixel of TFT screen .
Which steps am I missing? Can anybody suggest code of JPEG image rendering on TFT screen?

Sketch of transmitter:
#include "OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>

#define ENABLE_OLED //if want use oled ,turn on thi macro

#ifdef ENABLE_OLED
#include "SSD1306.h"
#define OLED_ADDRESS 0x3c
#define I2C_SDA 14
#define I2C_SCL 13
SSD1306Wire display(OLED_ADDRESS, I2C_SDA, I2C_SCL, GEOMETRY_128_32);
#endif

OV2640 cam;
WebServer server(80);

IPAddress apIP = IPAddress(192, 168, 1, 1);

void handle_jpg_stream(void)
{
    WiFiClient client = server.client();
    String response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
server.sendContent(response);

while (1)
{
    cam.run();
    if (!client.connected())
        break;
    response = "--frame\r\n";
    response += "Content-Type: image/jpeg\r\n\r\n";
    server.sendContent(response);

    client.write((char *)cam.getfb(), cam.getSize());
    server.sendContent("\r\n");
    if (!client.connected())
        break;
    }
}

void handle_jpg(void)
{
    WiFiClient client = server.client();

    cam.run();
    if (!client.connected())
    {
        return;
    }
     String response = "HTTP/1.1 200 OK\r\n";
     response += "Content-disposition: inline; filename=capture.jpg\r\n";
    response += "Content-type: image/jpeg\r\n\r\n";
    server.sendContent(response);
    client.write((char *)cam.getfb(), cam.getSize());
}

void handleNotFound()
{
    String message = "Server is running!\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
   message += "\nArguments: ";
   message += server.args();
   message += "\n";
   server.send(200, "text/plain", message);
}

void setup()
{
    Serial.begin(115200);
    while (!Serial)
    {
        ;
     }
camera_config_t camera_config;
camera_config.ledc_channel = LEDC_CHANNEL_0;
camera_config.ledc_timer = LEDC_TIMER_0;
camera_config.pin_d0 = 17;
camera_config.pin_d1 = 35;
camera_config.pin_d2 = 34;
camera_config.pin_d3 = 5;
camera_config.pin_d4 = 39;
camera_config.pin_d5 = 18;
camera_config.pin_d6 = 36;
camera_config.pin_d7 = 19;
camera_config.pin_xclk = 27;
camera_config.pin_pclk = 21;
camera_config.pin_vsync = 22;
camera_config.pin_href = 26;
camera_config.pin_sscb_sda = 25;
camera_config.pin_sscb_scl = 23;
camera_config.pin_reset = 15;
camera_config.xclk_freq_hz = 20000000;
camera_config.pixel_format = CAMERA_PF_JPEG;
camera_config.frame_size = CAMERA_FS_SVGA;

cam.init(camera_config);

WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
bool result = WiFi.softAP("TTGO-CAMERA", "12345678", 1, 0);
if (!result)
{
    Serial.println("AP Config failed.");
    return;
}
else
{
    Serial.println("AP Config Success.");
    Serial.print("AP MAC: ");
    Serial.println(WiFi.softAPmacAddress());
}

#ifdef ENABLE_OLED
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(128 / 2, 32 / 2, WiFi.softAPIP().toString());
display.display();
#endif

server.on("/", HTTP_GET, handle_jpg_stream);
server.on("/jpg", HTTP_GET, handle_jpg);
server.onNotFound(handleNotFound);
server.begin();
}

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

Sketch of receiver:
#include <WiFi.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <Adafruit_ImageReader.h> // Image-reading functions
//#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPI.h>
#include "WiFi.h"
#include <JPEGDecoder.h>
//#include <FileIO.h>

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS 16
#define TFT_RST 9  // you can also connect this to the Arduino reset
                  // in which case, set this #define pin to -1!
#define TFT_DC 17

// Option 2: use any pins but a little slower!
#define TFT_SCLK 5   // set these to be whatever pins you like!
#define TFT_MOSI 23   // set these to be whatever pins you like!
#define PIN_NUM_MISO 2
#define PIN_NUM_MOSI 15
#define PIN_NUM_CLK  14
#define PIN_NUM_CS   13

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK,     TFT_RST);

String text="";

const char* ssid     = "TTGO-CAMERA";
const char* password = "12345678";
const char* host     = "192.168.1.1";
const char* url      = "/";

IPAddress local_IP(192, 168, 1, 3);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8); //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional

//PImage logo;

#define BUFFPIXEL 20
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have     padding
  uint8_t  sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;               // pixel color for tft
  File     bmpFile; File     bmpFile1;
  uint32_t pos = 0, startTime ;
  uint8_t xx=0; uint16_t yy=0; int ww=0; int hh=0;
  int bmpfilepos;

//How to use -
//tft.fillScreen(ST7735_BLACK);
//testdrawtext(2,3,ST7735_GREEN,text);

void testdrawtext( int leftoffset , int topoffset , uint16_t color ,  String text ) {
  tft.setCursor(leftoffset, topoffset);  // (offset from left margin , offset from top margin. )
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.setTextSize(1);
  tft.print(text  );
    }

void jpegbytesdisplay()
{
 // Create a buffer for the packet
    char dataBuff[240];

    delay(5000);

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  int cnt=0;

  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the cam server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
           "Host: " + host + "\r\n" +
           "Connection: close\r\n\r\n");
  unsigned long timeout = millis();

  while (client.available() == 0)
  {
    if (millis() - timeout > 5000)
    {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

   int max_y=200;
   int ypos =200;
   int max_x=0 ;
   int xpos =0;

  // Read all the lines of the reply from server and print them to Serial

  ImageReturnCode stat;
  while (client.available())
  {
    //================================
   // String line = client.readStringUntil('\r');
   // Serial.print(line);

    //================================
    //bytes put into char[len] databuffer.
    size_t len=client.available();
    unsigned char buf[len];
    client.readBytes(buf, len);

    Serial.println("------------------------");
    Serial.println(len);
    //Serial.write(buf);

     //================================
     // bufffer to tft screen pixel rendering

      int col=0;
  int buffidx =0;
  cnt++;

    tft.fillScreen(ST7735_BLACK);
    tft.startWrite();
    tft.setAddrWindow(0, 0, 500, 500);

String fname="/image2" + String(cnt) + ".jpg";
File myFile = SD.open(fname, FILE_WRITE);
myFile.write(buf,len);
myFile.close();

     for (col=0; col<len; col++)
       {
          Serial.print(buf[col]);
       }
    Serial.println();
    Serial.println("------------------------");

      // For each pixel...
     for (col=0; col<len; col++)
     {
         if (buffidx >= sizeof(buf))
              {
          buffidx = 0; // Set index to beginning
                break;
        }

        b = buf[buffidx++]; //          [B]
        g = buf[buffidx++]; //     [G]
        r = buf[buffidx++]; //   [R]

        tft.pushColor(tft.color565(r,g,b));
                             // Display pixel on tft screen one after another.

   } // end pixel loop.

    //================================

   delay(1000);
    tft.endWrite();
  }

    }

 void setupNormal()
{

   Serial.begin(115200);

   // Use this initializer if you're using a 1.8" TFT
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab

  Serial.println("Initialized");

  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }

  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  tft.fillScreen(ST7735_BLACK);

}

void setup()
{

    setupNormal();
    jpegbytesdisplay();

      }

void loop()
{

}

Here is what i found for JPEG image file display on any TFT -
i used JPEGDecoder library and instead of tft.pushColor , i used tft.drawPixel  method.
  for (int jj  =mcu_y;jj<mcu_y + win_h;jj++)
     {
        for (int ii=mcu_x;ii<mcu_x + win_w ;ii++)
        {
            // TFTscreen.drawPixel(ii,jj,tft.color565(255,0,0));
             TFTscreen.drawPixel(ii,jj,*pImg++ );
        }
     }

For BMP , we need rgb values to render each pixel on TFT screen.
But in case of JPG , first  we need to decode and create MCU tiles on TFT.
Then we paint those MCU tiles by color which we receive from JPEG stream decoder.
Here *pImg is the pointer which hold the color information.
As we increment *pImg++ array , each time we receive new color code of type uInt8_t type . Within MCU tiles , these color have to be injected .
Each MCU tile is colored and drawn in the given sequence by considering where the border line of TFT screen is.
It automatically create a JPEG image .
//////////////////////////////////////////////////////////////
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <Adafruit_ImageReader.h> // Image-reading functions

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS 16
#define TFT_RST 9  // you can also connect this to the Arduino reset
                      // set these to be whatever pins you like!
// in which case, set this #define pin to -1!
#define TFT_DC 17

// Option 2: use any pins but a little slower!
#define TFT_SCLK 5   // set these to be whatever pins you like!
#define TFT_MOSI 23

Adafruit_ST7735 TFTscreen = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

//////////////////////////////////////////////////////////////

#include <JPEGDecoder.h>  // JPEG decoder library

//////////////////////////////////////////////////////////////
// include the necessary libraries
#include <SPI.h>
#include <SD.h>
//////////////////////////////////////////////////////////////

// pin definition for the Mega
#define sd_cs  53
#define lcd_cs 49
#define dc     48
#define rst    47

#define TFT_WHITE 0xFFFF
#define TFT_BLACK 0x0000
#define TFT_RED   0xF800

 //////////////////////////////////////////////////////////////

 #define PIN_NUM_MISO 2
#define PIN_NUM_MOSI 15
#define PIN_NUM_CLK  14
#define PIN_NUM_CS   13

  Adafruit_ImageReader reader;
    ///////////////////////////////////////////////////////

String text="";

// this function determines the minimum of two numbers
#define minimum(a,b)     (((a) < (b)) ? (a) : (b))

  //====================================================================================
    //   setup
    //====================================================================================

void setup() {
  // initialize the GLCD and show a message
  // asking the user to open the serial line
  //////////////////////////////////////////////////////////////////
   // Use this initializer if you're using a 1.8" TFT
  TFTscreen.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
//////////////////////////////////////////////////////////////////

  TFTscreen.fillScreen(TFT_WHITE); // Alternative:

TFTscreen.background(255, 255, 255);

TFTscreen.setTextColor(TFT_RED); // Alternative: TFTscreen.stroke(0, 0, 255);
  TFTscreen.println();
  TFTscreen.println(F("Arduino TFT Jpeg Example"));

  TFTscreen.setTextColor(TFT_BLACK); // Alternative: TFTscreen.stroke(0, 0, 0);
  TFTscreen.println(F("Open serial monitor"));
  TFTscreen.println(F("to run the sketch"));

  // initialize the serial port: it will be used to
  // print some diagnostic info
  Serial.begin(115200);
  while (!Serial) {
    // wait for serial port to connect. Needed for native USB port only
  }

  // clear the GLCD screen before starting
//  TFTscreen.background(255, 255, 255);
  TFTscreen.fillScreen(TFT_WHITE);

  // try to access the SD card. If that fails (e.g.
  // no card present), the setup process will stop.
  Serial.print(F("Initializing SD card..."));

//////////////////////////////////////////////////////////////////

  SPI.begin(PIN_NUM_CLK, PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CS);

  if (!SD.begin(PIN_NUM_CS)) {
    Serial.println(F("failed!"));
    while (1); // SD initialisation failed so wait here
  }
  Serial.println(F("OK!"));
//////////////////////////////////////////////////////////////////

  // initialize and clear the GLCD screen
 // TFTscreen.begin();
  TFTscreen.fillScreen(TFT_WHITE); // Alternative: TFTscreen.background(255, 255, 255);

  // now that the SD card can be accessed, check the
  // image file exists.
  if (SD.exists("/EagleEye.jpg")) {
    Serial.println("EagleEye.jpg found on SD card.");
  } else {
    Serial.println("EagleEye.jpg not found on SD card.");
    while (1); // Image file missing so stay here
  }

}

//====================================================================================
//   Main loop
//====================================================================================
void loop() {

  // open the image file
  File jpgFile = SD.open( "/EagleEye.jpg", FILE_READ);

  // initialise the decoder to give access to image information
  JpegDec.decodeSdFile(jpgFile);

  // print information about the image to the serial port
  jpegInfo();

  // render the image onto the screen at coordinate 0,0
  renderJPEG(0, 0);

  // wait a little bit before clearing the screen to random color and drawing again
  delay(4000);

  // clear screen
  TFTscreen.fillScreen(random(0xFFFF));  // Alternative: TFTscreen.background(255, 255, 255);
}

//====================================================================================
//   Print information about the image
//====================================================================================

void jpegInfo() {
  Serial.println(F("==============="));
  Serial.println(F("JPEG image info"));
  Serial.println(F("==============="));
  Serial.print(F(  "Width      :")); Serial.println(JpegDec.width);
  Serial.print(F(  "Height     :")); Serial.println(JpegDec.height);
  Serial.print(F(  "Components :")); Serial.println(JpegDec.comps);
  Serial.print(F(  "MCU / row  :")); Serial.println(JpegDec.MCUSPerRow);
  Serial.print(F(  "MCU / col  :")); Serial.println(JpegDec.MCUSPerCol);
  Serial.print(F(  "Scan type  :")); Serial.println(JpegDec.scanType);
  Serial.print(F(  "MCU width  :")); Serial.println(JpegDec.MCUWidth);
  Serial.print(F(  "MCU height :")); Serial.println(JpegDec.MCUHeight);
  Serial.println(F("==============="));
}

//====================================================================================
//   Decode and paint onto the TFT screen
//====================================================================================
void renderJPEG(int xpos, int ypos) {

  // retrieve infomration about the image
  uint16_t *pImg;
  uint16_t mcu_w = JpegDec.MCUWidth;
  uint16_t mcu_h = JpegDec.MCUHeight;
  uint32_t max_x = JpegDec.width;
  uint32_t max_y = JpegDec.height;

  // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
  // Typically these MCUs are 16x16 pixel blocks
  // Determine the width and height of the right and bottom edge image blocks
  uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
  uint32_t min_h = minimum(mcu_h, max_y % mcu_h);

  // save the current image block size
  uint32_t win_w = mcu_w;
  uint32_t win_h = mcu_h;

  // record the current time so we can measure how long it takes to draw an image
  uint32_t drawTime = millis();

  // save the coordinate of the right and bottom edges to assist image cropping
  // to the screen size
  max_x += xpos;
  max_y += ypos;

   char str[100];
  // read each MCU block until there are no more
  while ( JpegDec.read()) {

    // save a pointer to the image block
    pImg = JpegDec.pImage;

    // calculate where the image block should be drawn on the screen
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;

    // check if the image block size needs to be changed for the right and bottom edges
    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
    else win_w = min_w;
    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
    else win_h = min_h;

    // calculate how many pixels must be drawn
    uint32_t mcu_pixels = win_w * win_h;

    // draw image block if it will fit on the screen
    if ( ( mcu_x + win_w) <= TFTscreen.width() && ( mcu_y + win_h) <= TFTscreen.height()) {
      // open a window onto the screen to paint the pixels into
      //TFTscreen.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);
      //TFTscreen.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);
      // push all the image block pixels to the screen

 ////////////////////////////////////////////////////////

 // while (mcu_pixels--)
 // {
 // TFTscreen.pushColor(*pImg++);
 // } // Send to TFT 16 bits at a time

 ////////////////////////////////////////////////////////

 //  Write all MCU pixels to the TFT window

  for (int jj=mcu_y;jj<mcu_y + win_h;jj++)
     {
        for (int ii=mcu_x;ii<mcu_x + win_w ;ii++)
        {
            // TFTscreen.drawPixel(ii,jj,tft.color565(255,0,0));
             TFTscreen.drawPixel(ii,jj,*pImg++ );
        }
     }

 ////////////////////////////////////////////////////////

    }

    // stop drawing blocks if the bottom of the screen has been reached
    // the abort function will close the file
    else if ( ( mcu_y + win_h) >= TFTscreen.height()) JpegDec.abort();

  }

  // calculate how long it took to draw the image
  drawTime = millis() - drawTime; // Calculate the time it took

 // print the results to the serial port
  Serial.print  ("Total render time was    : "); Serial.print(drawTime); Serial.println(" ms");
  Serial.println("=====================================");

}


text:
Trying to power multiple servos at once using a Arduino Mega
Recently I have been trying to do a project for my end of year project, it involved making a humanoid arm.
I am still a newbie at these things, I usually have my friend do the wiring, but since he is away for the moment can anyone help me with it?
I am currently using 6X MG996R Servos for each finger and 1 for the wrist. I am also using a Arduino Mega with a Adafruit 16-Channel 12-bit PWM/Servo Shield - I2C interface.
I have already searched through the web for the best way to power it but I only found people trying to power it with a 5v adaptor, my problem is I'm trying to make the hand mobile so I need to use a battery. I have tried 2x UltraFire 18650 3000mAh 3.7V rechargeable battery in series (still doesn't work only 1 servo moved), also using a 9v battery (Only moved 2 servos).
So i have been wondering if I could utilise the Adafruit 16-Channel 12-bit PWM/Servo Shield - I2C interface..

Take a multimeter and test the voltages and amps while the servos are being used. If there is voltage drop you will need more batteries in parallel (equalize the voltages before connecting them).

Ok ratchet ill try that soon, oh and BTW do you think the Adafruit 16-Channel 12-bit PWM/Servo Shield - I2C interface will make a difference since as of now im suing a breadboard to control all the servos..

You do have the servo power lines connected in parallel, yes? All Power lines together at the battery, same with all Gnd lines, and the Gnd from the Mega as well.  Some folks have mistakenly connected the power lines in series, that will not work.

OK then i guess i will try to do both in series and parallel

read what @crossroads wrote .... do not do a series connection

Ok thx jsotola for your response ill try that

Here is a spec-sheet for the MG996R servos. Notice at the top of the 2d page, they require a supply of 4.8 - 7.2 volts, and can draw .5 - .9 Amps running and 2.5 Amps when stalled.
You'll need a supply of 6 volts (+/-) that can handle that current, times however many servos you need to operate simultaneously. The 3.7 volt batteries don't even meet the minimum voltage for the servos (unless you have two of them in series, but then they're slightly over the maximum).
You need to figure out your power budget first, then how your are going to meet it. You might be able to use a lighter supply than the worst case (6 stalled motors) would require or even than 6 motors at full operating torque (0.9 Amp each), if you monitor the current on each motor and shut down the or sequence the one(s) with the highest draw. You might even try monitoring just the battery-pack voltage, which won't tell you which motor(s) are stressing, but will let you know that you're unable to supply the total requirement for that present move.
If it were me, I'd use battery voltage sensing first (easier, simpler) to see if I have a problem that I can't solve by sequencing the motors. I might find I don't need to measure each motor's current.
Update:

So its either i use 3.7 bat or 9v. Or.can you suggest any other power
  source?

A single 3.7v battery won't work well) for a motor that needs 4.8v minimum. Two of them in series will be slightly over the max voltage spec (7.4v vs. 7.2v). Will that slight overage damage or overheat the motor? Will be OK for intermittent use? Maybe, if you're careful to shut down a stalled motor quickly. The alternative is to build a voltage regulator that will drop the 7.4 to around 6v, but the regulator must also be able to meet your power budget, too.
A 9v supply is definitely too high and will need to regulated to within the motors' spec. (I assume you're not considering the four or five cm high ones with snap-on connectors, usually used in smoke-detectors? They have very little capability to deliver current and will be totally unsuitable for your application.)
My first try would be to experiment with 1 motor at 7.4v with a typical (for your project) mechanical forces on it, and see if it overheats and how soon, with how much load. You'd be taking a bit of a risk with that motor but the potential advantage is you might save yourself having to build a high-current voltage regulator.
Update2:

NiMH AA cells are 1.2V

Good call. Just know that Nickle-based batteries have the twin disadvantages of long charge cycles (or degradation of capacity with faster charging) and higher self-discharge rate of about 1%/day. Their advantage to you is that it's easier to make a battery pack whose voltage falls within the motor spec. If this is a one-time project, this may well be more important to you than their disadvantages.

Ooo ill keep that in mind Jrobert, but my problem is in my country i cant seem to find any 5v NiMH battery which was my 2nd option if the 3.7 ultrafire bt wont work. So its either i use 3.7 bat or 9v. Or.can you suggest any other power source? And keep.i mind im trying to make the hand mobile

NiMH AA cells are 1.2V, use 4 of them in series to make 4.8V, 5 for 6V.

@CrossRoads ok i will try to find those in my country


text:
Does Arduino C++ support dynamic arrays of objects
My C++ is seriously out-of-date, and I'm working on a project that will be juggling multiple timed actions at the same time, with a menu system to manage the interface and control those timed actions (A multi-channel power outlet controller.)
To do the control I'm planning to have an array of objects that get serviced every time through the event loop. I'm currently using a static C array of objects, but I'd like to use a dynamic C++ array where I can add and remove objects as needed.
I know that some features of the C++ standard library are not supported on Arduino. I think C++ calls smart arrays vectors, and believe vectors are part of the standard library, which isn't supported/fully supported on Arduino. Is there some sort of dynamic array class available?

https://github.com/maniacbug/StandardCplusplus

what for a dynamic array? take as static array the maximum you can/need. there is no other process that could use the memory. on a simple AVR MCU with no concurency, you can exactly plan the memory

Even if it would be possible to use dynamic arrays, I would not recommend it, especially not on an Arduino Uno/Mega with only 2 or 8 KB memory.
Instead, create a static data element (e.g. array) that has a (reasonable) maximum number of created elements. This also has the benefit that the constructor will not be called after initialization, thus no variance in execution time (construction of objects can take time).
To manage multiple items within this data element, you can:

Using a ring buffer, this is the normal way to store items on one side, and process them from the other (so-called FIFO, first in first out).
Using a stack (for LIFO, last in last out).
For arrays, keep one variable that holds the number of elements currently filled.

Old-school C coding. Sure, I'm familiar with those techniques. I've been working too long on devices with tons of memory and plenty of processing power. It's been a long time since the days when I had to write apps in 8-bit assembler. These days I've come to rely on higher level constructs built into the language/OS. It's an adjustment for sure, and it's strange to have a language like C++ on a microcontroller. Causes some cognitive dissonance.

A simple singly linked list would work too.

@DuncanC I have the same issue ... being a software engineer, I think in lists, (dynamic) arrays, stacks, queues etc. A single linked list also is dynamic. Things get complicated when you need to insert elements in an existing list (and removing in some cases).

"Things get complicated when you need to insert elements in an existing list"? How so? Inserting and removing items seems easier with a list, not harder. Easier in some ways than a fixed array with empty flags for each entry

@DuncanC In a list it is easier, but that's dynamic, I mean within arrays, it's easier to remove items (by using a boolean array to show which elements are empty), but adding new items can only be done at the empty spaces (previously deleted array elements) or at the end. A list is always easier, but you need to allocate space for every element separately, thus it is a dynamic data type.

Actually, why bother with a boolean array? Just use NULL for empty slots, and check for NULL before acting on an entry in the array. Then I can add memory management that destroys objects as they are removed.

@DuncanC You are right, I will remove it from the answer.


text:
vscode arduino integration errors
I'm just trying to understand how vscode can compile arduino sketch. Now I uploaded some sketch to arduino and it was fine. Now I'm trying to add my own header files to .ino sketch and I got weird faults. I don't understand whats happening. I know this header files in under project.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "chcStandart.h"
#include "chcDefines.h"

When I try to verify my code I get this error:
> c:\Users\Desktop\Main_Code\chc.h:7:25: fatal error: chcStandart.h: No
> such file or directory

Also ı configured my json (c_cpp_prop) file and it looks like that.
"name": "Win32",
            "includePath": [
                "C:\\Program Files (x86)\\Arduino\\tools\\**",
                "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\**",
                "C:\\Program Files (x86)\\Arduino\\libraries\\**",
                "C:\\Users\\Musa Ünal\\Documents\\Arduino\\libraries\\",
                "C:\\Users\\Musa Ünal\\Desktop\\Main_Code\\**"

            ],
            "forcedInclude": [
                "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino\\Arduino.h"
            ],
            "intelliSenseMode": "msvc-x64",
            "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.14.26428/bin/Hostx64/x64/cl.exe",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "C_Cpp.intelliSenseEngine": "Tag Parser"

My question is: How I can handle this problem? Thanks!

Where is the file chcStandart.h? The tool is looking for it at c:\Users\Desktop\Main_Code\chcStandart.h

Yes, its under the project, same file with my .ino file

do you have #include "chcStandard.h" or #include <chcStandard.h>  in chc.h?

Ok problem solved, if anybody have the same problem you should add "${workspaceRoot}" to your path


text:
Checking Arduino 5/3.3V under load
Is there a way to use common/cheap components to put the 3.3V and 5V pins on an Arduino under load, in order to measure if they are giving a correct and stable voltage?  Can I calculate a certain load to test?
Something keeps happening to my boards which causes the 3.3V pin to measure the correct voltage when idle, but to spike when put under load, which kills the component I was powering (XBees, which are previously tested working).

resistors are as cheap as you are going to get.

Arduino 3.3V source is only good for 150mA. The 5V source for 500mA from USB source, and maybe 700-800mA from the barrel jack if the source voltage is up to about 7.5V, and less current as you get up to 9V, and even less with 12V, the poor 5V regulator will heat up and shut down.

When putting too much load on a power source, the voltage will only dip down (to lower voltages). How can this kill other components? More likely it will stop working, until the voltage is sufficient again. Or are you also having motors or such connected to it without proper protection?

why would you power the XBee from an Arduino I/O pin?

Thanks all, I purposefully kept my project specific stuff away to keep this a generic question about testing load.
@ratchetfreak Thanks, I expected testing load to involve resistors, do you have an answer on how to actually reliably test those pins using them... ie if you connect resistors in series equalling X ohms and measure X Ma current across a specific point you know your regulator is handling the load that the arduino is expected to handle?

@jsotola it is powered by the 3.3V pin, and uses I/O pins for communication only

@chrisl Thanks,  do you know what situations could be causing the spikes up to higher voltages?  No motors or other components were connected while testing these spikes, but there were previously several MOSFET controlled LEDs  and other components incl solenoids which the arduino was controlling, powered by 12V VIN.

solenoids and relays can create spikes. The easiest way to mitigate them is using a flyback diode. Though most boards will additionally opto-isolate them from the control pins.


text:
How to get PWM frequency to ~14KHz?
I found this question:
Set PWM frequency to 25 kHz
It is useful, however, I want to use it to generate ~14KHz?
int d = 0;            // pwm value

void setup()
{
  //  Sets Timer1 to Phase Correct
  //  F_CLOCK / ( Prescaler * ORCR1A * 2 ) = Freq in Hz
  //  16000000 / (1 * 512 * 2 ) = 15625 Hz
  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);  // Phase Correct
  TCCR1B = _BV (WGM13) | _BV (CS10);                  // Phase Correct / Prescale 1
  OCR1A = 571;                                        // Sets Top to 512 --571
  OCR1B = 0; // Sets Pwm =
    pinMode(10, OUTPUT);
    pinMode(0, INPUT)
}

void loop()
{
  d = (analogRead(0));
  d = map(d, 0, 1023, 0, 512);
  OCR1B = d;
}

I used this sketch to test the frequency which works good. If I change the pinMode(10, OUTPUT);, into: pinMode(9, OUTPUT); and there is no output, why?

The top of timer1 is set to 320. I think that a value of 571 will result in about 14010.5 Hz. Can you tell which sketch you are using and please tell us what it is for.

Thank you Jot, I'll use the last code in the 'Set PWM frequency to 25 kHz' to control a motor driver which asked a PWM frequency about 14KHz.

Please keep in mind that this site is for questions and answers. Preferably good and clear questions and one or more good and clear answers. This is the pinmapping for an arduino uno and nano: https://www.arduino.cc/en/Hacking/PinMapping168 Pin 10 is OC1B and pin 9 is OC1A. That are outputs of timer1. In the datasheet of the atmega328p you can find how the pwm modes are used and how the output pin (or internal interrups) can be used with pwm. You map the signal up to 512, but the pwm counts to 571, so your maximum pwm is 89%.

Take this sketch, replace 320 by 571 and do not change anything else.

Thank you Edgar, both pin 9 and 10 working now.

When I put this PWM code into my driver code, there was conflict of using timer1 with VirtualWire library. How can I use timer2 to get 14khz? I am using UNO.

laoadam, to get someone's attention use for example @Jot then I will be notified. Timer2 is only 8 bits and has other output pins. You can move the VirtualWire to Timer2. Upgrade to RadioHead in RH_ASK mode and change it to Timer2 (search for "timer2" on this page: https://www.airspayce.com/mikem/arduino/RadioHead/classRH__ASK.html ). RadioHead uses a lot more memory than VirtualWire.

@Jot Thank you Jot, I have shift the PWM frequency set by Timer2, output by P3 and P11, it's works well now at ~3.9 KHz, no yet what I need ~14khz, at lest made progress. There is new problem came up when I use this sketch on my 30A motor driver which has (PWM1+DIR1) for motor 1, but the original sketch used (PWM1+AIN1+AIN2) to control motor 1.

With timer1 the resolution was 571 steps and with timer2 it is below 256. I forgot about all those pwm modes, so I'm not sure if timer2 has the same pwm mode as timer1. You make it seem as if you  want to control a stepper motor with pwm. I don't understand that. You can ask a new question for the pwm/dir/ain signals. Tell what motor it is, what the driver is, what the signals from the arduino are, with links, schematics, pictures, photos, everything.

@ Jot, thank you Jot, the timer2 does not works that way. I have post another question.


text:
Can Serial be safely used in an SPI interrupt routine
I have anecdotal experience that using Serial.print inside a slave's SPI interrupt routine (ISR) causes issues with transmission. It also seems that interrupts may be called more than once before the main loop can react, so it is difficult to print info from all interrupts. Is this because Serial is inherently unsafe, or too slow? Can Serial be used safely inside the ISR routine?

it is not a surprise that the answer with most votes follows the dogma. but no, Serial print or write doesn't hang in interrupt.  It was fixed in 2013. https://github.com/arduino/ArduinoCore-avr/commit/dbe23685c27cb1467dc84140e4899a0bf8e23248

Serial should be avoided in ISRs because interrupts are disabled inside ISRs, and Serial transmission uses interrupts to operate. Better to have the ISR set a flag that is read in the next iteration of loop() to print the desired info.

Hardware Serial write(byte) function in Arduino AVR core will work in interrupt. It checks if interrupts are disabled and if yes and the buffer is full, it executes directly the interrupt function, which pushes bytes from buffer to output.

@Juraj is write or print re-entrant?

it doesn't need to be re-entrant

@Juraj That is interesting to know. I was unaware of that behavior

@josecanuc, it contradicts you answer, but the question is about SPI slave where it can mess with timing or I don't know what else

Feel free to vote my answer accordingly. I did write it as it applies more generically and does not address the specific issue of slave SPI ISR. Better answers are encouraged and should be voted up!

The biggest problem I had was when the tx-buffer was full and I did an Serial.print inside an ISR. Using the highest baudrate fixed the issues I had. But I only used it for debugging, and won't really trust it for production code.

@Gerben, it was before this? https://github.com/arduino/ArduinoCore-avr/commit/dbe23685c27cb1467dc84140e4899a0bf8e23248

Hardware Serial write(byte) function in Arduino AVR core will work in interrupt. It checks if interrupts are disabled and if yes and the buffer is full, it executes directly the interrupt function, which pushes bytes from buffer to output.
(All write and print functions of hardware Serial use the write(byte) function to send data.)
It depends on other factors if a long time spent in interrupt handler will disturb things.

In general, interrupts should run as fast as possible. This is especially true when using SPI, since in the slave's ISR, the slave needs to put a byte in the SPI Data Register (SPDR) before the next transfer occurs. Thus it is good practice to avoid Serial transmission entirely in an interrupt, since in simple interrupts it can be by far the slowest portion of the interrupt.


text:
Dynamically modifying the call stack using pointers
In a C++ Arduino library, can we modify the call stack from inside a function by intentionally decrementing a pointer to a stack variable so that it's out of range? Like this:
void FooBar()
{
  char a;
  char *ptr = &a;
  ptr -= 4;
  // Can we edit the call stack with ptr now?
}

Can we use this to, for example, change what function is "calling" FooBar() by replacing the function pointer of the calling function on the call stack to another function? Or can we change the values of function variables in the calling function in mischievous fashion?

Yes, you can. Learn the ABI first so you know what is where. https://gcc.gnu.org/wiki/avr-gcc#Frame_Layout However I wouldn't recommend doing so - nasty things can happen if you futz with the stack frame.

Yes, you can, but it won't work. The compiler can do many optimizations, so it is very doubtful that it will work. When you are serious about writing software, then you should never do such things. Stay far away from things that are bound to go wrong. Every software engineer that sees your piece of code is now feeling very uncomfortable and is banging his/her head against the wall screaming out loud: no, no, no.

I recommend you to generate an .lst file and see the assembly

I am answering in the context of the AVR calling conventions, as they
are the only ones I know well enough to be able to answer here.

Can we use this to, for example, change what function is "calling"
  FooBar() by replacing the function pointer of the calling function
  on the call stack to another function?

That will probably be impossible in C++. Let's say you have the
following call chain: main() → f() → FooBar(). In the body of
FooBar(), the stack will look like this (oldest stuff at top):
return address from f() to main()
registers saved by the f() prologue
return address from FooBar() to f()
registers saved by the FooBar() prologue

Getting the stack pointer is easy. No need to declare a dummy variable,
just:
char *stack_pointer = (char *) SP;

Now, to change the required return address, you need to skip over the
registers saved by the FooBar() prologue. And this is the big problem:
you do not know how many registers were saved there. Function prologues
are written by the compiler, and whatever they save depends on how many
registers are needed within the function, which in turn depends on the
complexity of that function. Even minor changes to the function can
modify the number of registers its prologue saves.
The only solution to this problem I can imagine is to forego the
compiler-generated prologue and write FooBar() in assembly. If you
wish to do it within a C++ file, you can attach the "naked" attribute to
the function and write its body using inline assembly.

Or can we change the values of function variables in the calling
  function in mischievous fashion?

No need to tamper with the stack for this. The compiler strives to store
as many local variable as possible in CPU registers rather than the
stack. The caller's local variables are most likely still in those
registers and you can modify them at will (in assembly). That's why you
have this register-saving prologue and register-restoring epilogue in
the first place. Indeed, if you make the function "naked" and don't do
the saving/restoring yourself, you will very likely end up corrupting
the caller's locals.


text:
ESP-13 WiFi shield - "error: espcomm_upload_mem failed"
I am creating a web server with Arduino and a ESP-13 WiFi shield. The wiring is as following:
Arduino UNO || ESP-13 WiFi shield
5V          || .5V
GND         || GND
TX          || RX
RX          || TX
            || GPIO 0 to GND

When I run my code, I get an error. The error is
warning: espcomm_sync failed
error: espcomm_open failed
error: espcomm_upload_mem failed
error: espcomm_upload_mem failed

I have tried many videos, tests and rewiring but nothing is working. If this would help, before I upload my code, the led on the wifi shield is red. When I am uploading my code, the Arduino Uno flashes between the RX and TX leds. The code:
#include <ESP8266WiFi.h>

/*==========================================================================
 * Project: ArduinoBasics WiFi Scanner
 * Author:  Scott C
 * Date created: 16 September 2018
 * Arduino IDE version: 1.8.5
 * Operating System: Windows 10 Pro
 *
 * Description:
 * The ESP-13 WiFi shield will create an Access Point that you can connect to
 * using your phone/tablet/PC. Once connected via WiFi, navigate your browser
 * to the IP address displayed in the Serial monitor to see the list of Access Points in your area.
 *
 * Acknowledgements:
 * Some of the code used within this sketch was inspired by or adapted from other notable sources.
 *    Webserver code: adapted from https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/server-examples.html
 *    WiFi scanner code adapted from tablatronix : https://gist.github.com/tablatronix/497f3b299e0f212fc171ac5662fa7b42
 *    HTTP/1.1 protocols: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 *
 * -------------------------------------------------------------------------
 * LIBRARIES:
 * Libraries used: ESP8266WiFi.h  - installed with Boards Manager : https://github.com/esp8266/Arduino
 * More information about ESP8266WiFi.h library :
 * https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html
 * https://arduino-esp8266.readthedocs.io/en/2.4.2/libraries.html#wifi-esp8266wifi-library
 *
 *
 * GLOBAL VARIABLES:
 * The SSID and Password for the Access point (AP) that will be created by the ESP-13 WiFi shield
 * The WiFi server which will listen for Clients on Port 80 (eg. Web Browsers)
 ============================================================================ */

const char* ssid = "PinkFluffyUnicorn";
const char* password = "12345678";
WiFiServer server(80);

/* ==========================================================================
 * SETUP:
 * Begin Serial Communication using a Baud Rate of 115200
 * Configure the ESP-13 WiFi shield into Access Point Mode
 * Create an Access Point for devices to connect to.
 * Display the Access Point (AP) IP address in the Serial monitor.
 * Start the server if the Access Point has been created successfully
 ============================================================================ */
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  boolean r = WiFi.softAP(ssid, password);

  if (r) {
    server.begin();
    Serial.println("");
    Serial.print("Please connect to the Access Point: ");
    Serial.println(ssid);
    Serial.printf("then open %s in a web browser\n", WiFi.softAPIP().toString().c_str());
    Serial.println("");
  } else {
    Serial.println("FAILED to create Access Point");
    while(1){}
  }
}

/* ==========================================================================
 * LOOP:
 * Start listening for Clients
 * Notify when a Client connects to the server using the Serial Monitor
 * Then write any request messages from the client to the Serial Monitor
 * Wait for the client to send through an empty line, then
 * Serve the constructed HTML page to the client
 * The delay gives the browser some time to receive the HTML page, before
 * the server dicsonnects from the client.
 * Notify when the client has been disconnected.
 ============================================================================ */
void loop() {
  WiFiClient client = server.available();
  if(client){
    Serial.println("\n A Client just connected to the server");
    while(client.connected()) {
      if(client.available()){
        String clientMessage = client.readStringUntil('\r');
        Serial.print(clientMessage);
        if(clientMessage.length() == 1 && clientMessage[0] =='\n') {
          client.println(constructHTMLpage());
          break;
        }
      }
    }
    delay(1000);
    client.stop();
    Serial.println("\n The server has disconnected the Client");
  }
}

/* ==========================================================================
 *constructHTMLpage:
 *SCAN for available WiFi networks within range of the ESP-13 WiFi Shield
 *Construct the necessary HTTP response and HTML to
 *  - display the SCAN results within a web browser (client).
 *  - automatically refresh the HTML page every 5 seconds.
 *
 *The HTML page will display the following information in a table:
 *  - SSID,
 *  - Signal Strength and
 *  - Encryption type.
 ============================================================================ */
String constructHTMLpage(){
  int numSSID = WiFi.scanNetworks();
  String HTMLpage = String("HTTP/1.1 200 OK\r\n") +
                            "Content-Type: text/html\r\n" +
                            "Connection: close\r\n" +
                            "Refresh: 5\r\n" +
                            "\r\n" +
                            "<!DOCTYPE HTML>" +
                            "\r\n" +
                            "
WIFI NETWORKS
\r\n" +
                            "

SSID	Signal Strength	Encryption type
\r\n";

  for(int i=0; i<numSSID; i++){
    HTMLpage = HTMLpage + String("
");
    HTMLpage = HTMLpage + String(WiFi.SSID(i));
    HTMLpage = HTMLpage + String("	");
    HTMLpage = HTMLpage + String(WiFi.RSSI(i));
    HTMLpage = HTMLpage + String("	");
    HTMLpage = HTMLpage + String(encryptionTypeStr(WiFi.encryptionType(i)));
    HTMLpage = HTMLpage + String(" [");
    HTMLpage = HTMLpage + String(WiFi.encryptionType(i));
    HTMLpage = HTMLpage + String("]");
    HTMLpage = HTMLpage + String("
");
  }
  HTMLpage = HTMLpage + String("
\r\n");
  return HTMLpage;
}

/* ==========================================================================
 *encryptionTypeStr:
 *Will accept a WiFi.encryptionType() integer and convert it into a more
 *meaningful string.
 ============================================================================ */
String encryptionTypeStr(uint8_t authmode) {
    switch(authmode) {
        case ENC_TYPE_NONE:
            return "OPEN";
        case ENC_TYPE_WEP:
            return "WEP";
        case ENC_TYPE_TKIP:
            return "WPA_PSK";
        case ENC_TYPE_CCMP:
            return "WPA2_PSK";
        case ENC_TYPE_AUTO:
            return "WPA_WPA2_PSK";
        default:
            return "UNKOWN";
    }
}

Thank you in advance.

Don't cross post. You already asked this on SO.

GPIO 0 to GND - doesn't that put the ESP into flash mode?

before you run the code you must upload it. why do you have the module wired to Uno, if you have a sketch for esp8266? I know why. You abuse the Uno as USB adapter. But then wire TX to TX, RX to RX. (and make sure the ATmega sketch doesn't have Serial.begin())

I deleted the Serial.begin(), but I am still getting the same error.

Also, I've changed my wiring. I'm using a serial to usb adaptor:

Adaptor | ESP-13 WiFi


text:
How do I use a 5v/120v relay that is not mounted on a board
I bought an arduino kit, and it came with, amongst other things, a 5v relay to control 120-220v.
The relay is only that, there is only the 5 pin relay, and it's not on a board on which one can screw in the leads

I was wondering how I can use it..  i.e. how do I mount it somehow (especially since the leads are metric and most perf board is standard (or vice-versa)).
I don't mind soldering the 5v control leads from the arduino, but I'm not so sure about soldering or connecting 110v straight on the relay.  i'm worried about long term longevity.
I have soldered longer leads just to be able to fit it on a board for tests, but those are tiny, and aren't safe for higher voltage/current.
Any suggestions?
Thanks, Seb.

This question is not about Arduino, but DO NOT connect mains to the relay - this would violate all the basic safety rules.

What I did with a similar looking 'module' (An AC/DC converter), was to use a protoboard/perfboard. Some holes fitted in the existing holes, others I drilled with a small drill.
On the back you can solder the wires you need, so for the 110V wires you might use thicker wires than for the controls.
Than if you want to make it fancy, you add some terminal blocks to connect the external wires too. Terminal blocks looks like this:

thanks for the answer. so you're saying I should simply make the relay fit on a perfboard, then bring the 110v wires right to it. or make a bridge with actual 110v wires rather than soldering or smaller wires.  at this point is there an advantage to using a perfboard at all instead of simply soldering straight to the relay?  would it be to solidify the whole aparatus;  have some form of a structure?

well actually you do not really 'use'  the perfboard, only a fixed straight piece of material. So you also can use any other material; do not use the small wires from the perf board for 110/220V. The main reason to use perfboard, is you can have the relay fixed and also put the remainder of your (logic level) signals throught the perfboard. Or you can can use pin headers to 'mount'  the 'relay perf board' on top of the real circuit, and connect the 110/220V wires directly to the pins of the relay.


text:
Nested "switch" statements menu
I know that menus were discussed perhaps a thousand times here and everywhere. But using a ready solution is not something that I'm looking for because I know I won't learn the concept if I use them. Hence the question.
I am trying to build a simple timer with a setup menu. The timer code works so that part of the code is not a problem. The menu is an adaption of a code I found online which I understand, and for the most part, works as long as I am in level 1. My menu will have 2 levels. the structure of the menu is something like this:
Option 1: Display Timer 1
Option 2: Display Timer 2
Option 3: Reset Timer 1
Option 4: Reset Timer 2
Option 5: Set Timer 1 Action Delay

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

Option 6: Set Timer 2 Action Delay

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

The menu will be displayed with an I2C 1602 LCD Screen, and navigation will be by way of 3 push buttons: Up, Down, and Select.
I am using a nested "switch case" statement to navigate between the menus.
So as long as I'm in level 1, everything works. the times are displayed, reset works, and all is well. The moment I go to a submenu, the first option in the submenu is selected immediately and the display shows the parent menu.
I am putting the menu code in a function, the submenu code in another function. Once the menu with a submenu is selected, it calls the submenu function.
My current code is as follows: [Note: Updated with a function to handle screen updates based on @jsotola]
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

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

LiquidCrystal_I2C lcd(0x27,16,2);

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

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

int pageCount   =   7;  //Main Menu

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

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

boolean last_up_s     =   LOW;
boolean last_down_s     =   LOW;

boolean current_up_s    =   LOW;
boolean current_down_s  =   LOW;

String line1;
String line2;

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

//LCD Function

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

//Menu Function
void Menus(){

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

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

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

        last_up = current_up;

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

          }
          else{
          page_counter= 1;
         }
        }

        last_down = current_down;

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

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

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

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

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

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

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

            delay(3000);
            lcd.clear();

        }
    }
    break;

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

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

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

            delay(3000);
            lcd.clear();

        }
    }
    break;

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

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

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

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

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

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

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

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

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

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

  }//switch end

}

void submenu(){

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

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

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

        last_up = current_up_s;

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

          }
          else{
          page_counter_s = 1;
         }
        }

        last_down = current_down_s;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  }//switch end

}

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

void loop() {

  Menus();
}

So, my first question is: What is going wrong with the submenu?
and my second question is: in the submenu, how do I exit back to main menu?
Any assistance will be much appreciated.
Thank You.

your LCD screen display code repeats multiple times with differing parameters ..... use a function that accepts two strings for the two lines and a boolean for clearing screen

@jsotola Hi. I have updated the code with a function to handle the screen printing. the code is in the question. The issue is still there. When I select option 5 or option 6 of the main menu, the program directly sets the delay to option 5.1 without allowing the user to navigate then select.

the function i was talking about is in this form printlcd("Set 02", "Interval", true); ..... that would display the two lines ... the true means clear screen ..... see https://arduino.stackexchange.com/questions/3059/functions-with-string-parameters .... read the comment at the accepted answer

the break statements should be inside the case block (inside the {} brackets) .........checking your code for logic errors

@jsotola Thank you very much. I'll look into the function and put the break statements inside the case blocks. Did you find any logic errors?

use pointers bro it will handle your problem though

you can use a menu library, there are many on github... my fav. ofcoz https://github.com/neu-rah/ArduinoMenu


text:
'inet_addr_to_ipaddr' was not declared in this scope
I am using ESP32 Ping from this page: https://github.com/pbecchi/ESP32_ping
It works fine on ESP32, no compiler error.
Because something wrong on my PC, I did fresh install Windows 10 and Arduino IDE 1.8.8.
After fresh install, ESP32 Ping doesn't work anymore.
Arduino IDE Compiler error in Ping.cpp:
//Ping.cpp

#include <Arduino.h>

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

#include "ping.h"

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

static uint16_t ping_seq_num;
static uint8_t stopped = 0;

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

#define PING_ID 0xAFAF

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

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

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

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

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

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

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

    ping_prepare_echo(iecho, (uint16_t)ping_size);

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

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

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

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

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

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

            strcpy(ipa, inet_ntoa(fromaddr));

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

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

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

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

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

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

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

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

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

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

                return;
            }
            else {
                // TODO
            }
        }
    }

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

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

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

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

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

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

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

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

    // Setup socket
    struct timeval tout;

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

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

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

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

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

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

    ping_seq_num = 0;

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

    closesocket(s);

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

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

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

    ping_opt->recv_function = ping_recv;
    return true;
}

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

    ping_opt->sent_function = ping_sent;
    return true;
}

Arduino IDE 1.8.8. compiler stop in this line:
inet_addr_from_ipaddr(&to.sin_addr, addr);

The error message: 'inet_addr_to_ipaddr' was not declared in this scope
According to this post, inet_addr need lwip library.
So... the conclusion: cause of this issue is broken lwip library.
But when ESP32 Ping working fine previously, I didn't install any separate lwip library. Maybe ESP32 Ping use lwip library from Arduino library - #include <Arduino.h>
But why after fresh install, ESP32 Ping doesn't work anymore?
Arduino IDE installation automatically included Arduino library. Also, I didn't change anything on Arduino Sketch & Library folder - C:\Users\Documents\Arduino. The folder content as the same as before fresh install.
How to fix this?
Please help...

did you use git to install the esp32 boards?

did the install of ESP32 package in Board Manager finish without errors?

@Juraj - ESP32 package installation in Board Manager finished without any errors but when compile the sketch always error 'inet_addr_to_ipaddr' was not declared in this scope

I did search all Ping.cpp included files in C:\Program Files (x86)\Arduino folder. ALL included files has been found in that sub folder EXCEPT ip4.h. The ip4.h file doesn't found in that folder, maybe this is the cause of broken lwip library. How to fix this?

Found ip4.h in C:\Users\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\tools\sdk\include\lwip\lwip. It seems ESP32 Ping use 2 separate lwip libraries (Arduino libraries in C:\Program Files (x86)\Arduino and ESP32 library in C:\Users\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\tools\sdk\include\lwip\lwip). But somehow the library connection is broken and cause 'inet_addr_to_ipaddr' was not declared in this scope error

Instead using Board Manager to install ESP32 package, also tried install it by using git, but didn't help either. Still 'inet_addr_to_ipaddr' was not declared in this scope error

Tried very dumb solution by adding #define inet_addr_from_ipaddr and
#define inet_addr_to_ipaddr in Ping.cpp file. No compiler error and able upload the sketch into ESP32, but ping doesn't work because it didn't find inet_addr_from_ipaddr and inet_addr_to_ipaddr functions.

Did searching in folders: C:\Program Files (x86)\Arduino, C:\Users\AppData\Local\Arduino15\ , and C:\Users\Documents\Arduino , NOT FOUND any inet_addr_from_ipaddr and inet_addr_to_ipaddr functions. Maybe this is the cause 'inet_addr_to_ipaddr' was not declared in this scope error. But how to fix this?

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

Then.... compile my sketch.
And now.... it WORKS....  :)  :)  :)
My previous mistake is not installing ESP32 Core version 1.0.0.
I did it by installing version 1.0.1 - the Boards Manager default version - which didn't work.
It seems some change in ESP32 Core version 1.0.1 broke ESP32 Ping library connection.

and why this answer? there is a simpler way to reinstall a boards package


text:
How to combine strings and text together?
I'm trying to combine two strings (strings/int) together with text in below code:
int foo = String((char*)payload).indexOf(' ');
int message1;
int message2;

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

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

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

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

message1 + " " + message2? you know what operator + does on int

What type is payload? Is it a dynamically allocated char array?

I wouldn't use the String class, but instead use the C functions to concatenate strings (like strcat, strncat).
You can use the itoa function to convert an integer to a string, see:

https://stackoverflow.com/questions/9655202/how-to-convert-integer-to-string-in-c

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