text:
Crash when serving static files width ESP8266WebServer
For the past two days, I've been trying to set up an ESP8266WebServer to serve my static web app files from SPIFFS. But as soon as I make a call to serveStatic, the ESP crashes. This is the exact code I'm running:
#include <FS.h>
#include <ESP8266WebServer.h>

ESP8266WebServer s;

void setup() {

    Serial.begin(115200);

    if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
    }

    s.serveStatic("/", SPIFFS, "/static/");
    s.begin();
}

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

I know that this is example does not allow me to access the files in any way because I don't have WiFi configured, but this is enough for me to crash the ESP. This is the error that I keep seeing:
SPIFFSImpl: allocating 512+240+1400=2152 bytes
SPIFFSImpl: mounting fs @100000, size=2fa000, block=2000, page=100
SPIFFSImpl: mount rc=0

Fatal exception 28(LoadProhibitedCause):
epc1=0x4021407a, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000

Exception (28):
epc1=0x4021407a epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffca0 end: 3fffffc0 offset: 01a0
3ffffe40:  3ffefaf8 00000000 3ffffea0 402127b1
3ffffe50:  00000001 ffffffff 4020a9dc 00000000
3ffffe60:  3ffe8304 00000000 0000000a 40216e21
3ffffe70:  402497e1 00000000 00000000 4020b414
3ffffe80:  3ffffee0 3ffffed0 00000008 402497e3
3ffffe90:  402497e2 3ffe8304 3ffefaf8 402171ec
3ffffea0:  00000000 ffffffff 00000000 00000000
3ffffeb0:  00000001 00000041 3f302073 40212d8e
3ffffec0:  3ffffee0 3ffffed0 00000004 40209c90
3ffffed0:  3fffff10 00000000 00000017 3fff0580
3ffffee0:  00308658 3fffff20 3ffef85c 4020a3e9
3ffffef0:  000018c0 3ffee6b0 00000000 40208120
3fffff00:  3fffff60 3fffff50 00000014 00000001
3fffff10:  00000009 00000001 00000001 40207c65
3fffff20:  40100b04 00001000 00002000 3fff0580
3fffff30:  3ffe8658 402497a4 3ffe8304 40212d8e
3fffff40:  3fffff60 3fffff50 00000004 40100476
3fffff50:  3ffe8658 3ffe8658 3ffe865f 00000000
3fffff60:  00000000 00000000 3fff056c 4020ffa5
3fffff70:  3fffdad0 3ffee690 3fff056c 40201325
3fffff80:  3ffe865f feefeffe feefeffe feefeffe
3fffff90:  feefeffe feefeffe feefeffe 3ffee610
3fffffa0:  3fffdad0 00000000 3ffee5d0 40206aa0
3fffffb0:  feefeffe feefeffe 3ffe84f4 40101245
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1392, room 16
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld

I have also analyzed the stack trace using ESP exception decoder, which didn't get me any further though. Here is the output of that tool:

Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
PC: 0x4021407a: pgm_read_byte_inlined at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/sys/xtensa/sys/pgmspace.h line 72
EXCVADDR: 0x00000000

Decoding stack results
0x402127b1: _printf_i at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 226
0x4020a9dc: spiffs_object_find_object_index_header_by_name_v(spiffs*, spiffs_obj_id, spiffs_block_ix, int, void const*, void*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 1664
0x40216e21: __sfputs_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 433
0x4020b414: spiffs_obj_lu_scan(spiffs*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_nucleus.cpp line 439
0x402171ec: _vfprintf_r at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 667
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40209c90: SPIFFS_mount(spiffs*, spiffs_config*, u8_t*, u8_t*, u32_t, void*, u32_t, spiffs_check_callback) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 138
0x4020a3e9: SPIFFS_stat(spiffs*, char const*, spiffs_stat*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs/spiffs_hydrogen.cpp line 769
0x40208120: spiffs_impl::SPIFFSImpl::_tryMount() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.h line 320
0x40207c65: spiffs_impl::SPIFFSImpl::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/spiffs_api.cpp line 80
0x40100b04: get_poisoned(void*, size_t) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/umm_malloc/umm_poison.c line 112
0x40212d8e: printf at /home/earle/src/esp-quick-toolchain/repo/newlib/newlib/libc/stdio/printf.c line 61
0x40100476: pvPortMalloc(size_t, char const*, int) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/heap.cpp line 267
0x4020ffa5: fs::FS::exists(char const*) at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/FS.cpp line 363
0x40201325: setup() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h line 75
0x40206aa0: loop_wrapper() at /Users/alex/Library/Arduino15/packages/esp8266/hardware/esp8266/2.6.3/cores/esp8266/core_esp8266_main.cpp line 177

These are my settings in the Arduino IDE:

To flash the data to the ESP, im using the latest version of this tool for the Arduino-IDE: https://github.com/esp8266/arduino-esp8266fs-plugin
I'm probably making a stupid mistake but I've been scratching my head for hours now and can't see where the issue could be. Any help would be greatly appreciated!
EDIT #1:
The data is definitely available on the ESP, since this snippet works fine:
#include <FS.h>
#include <ESP8266WebServer.h>

ESP8266WebServer s;

void setup() {

    Serial.begin(115200);

    if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
    }

    /*s.serveStatic("/", SPIFFS, "/static/");
    s.begin();*/
}

void loop() {
  //s.handleClient();

    delay(5000);

    File f = SPIFFS.open("/static/index.html", "r");

    String s = f.readString();

    Serial.println(s);

    f.close();
}

EDIT #2
Serving the files by registering the function below as a handler (server.on("/", myHandler)works:
void myHandler(){

    String file = "/static/index.html";

    Serial.println("[INFO] requested file " + file);

    if(!SPIFFS.exists(file)){

        server.send(404, "text/plain", "
404: Not found
");
        return;
    }

    String contentType = "text/plain";

    if(file.endsWith(".html")){
        contentType = "text/html";
    } else if(file.endsWith(".css")){
        contentType = "text/css";
    } else if(file.endsWith(".js")){
        contentType = "application/javascript";
    }

    File f = SPIFFS.open(file, "r");

    server.streamFile(f, contentType);

    f.close();
}

try to turn off the debug logs with "Debug level" None

tried that before, didn't help unfortunately

are you sure? do you have the same stack trace then? turn off Debug port too

Wow, I just tried it again - and you were right! It's working now! Maybe I had just turned down the level before... But why? Does that mean I can't look at my WiFi-Debug-Messages while using serveStatic()?

I've just done some testing and figured out that as soon as I include CORE in the debugging menu, it starts crashing. I would have never guessed this was the issue.

there must be some bug with logging. printf in stack trace was the clue

Great find! Shame I can't upvote you!

Turns out the ESP crash is caused by the debug settings in the Arduino IDE. As soon as the CORE-level is included, the error occurs. There seems to be a bug in the firmware somewhere. Including other levels seems to be fine.
A huge thanks to Juraj for helping me spot this one.

Probably you have no SPIFFS uploaded. So after flashing the program you have to use ESP8266DataUpload and in your Dir containing the *.ino there has to be a "data" directory in which the file you serve or the dir in your case "/static/" has to exist.
EDIT No the file is not existing ;-) use
 serveStatic("/", SPIFFS, "/static");  //=> no trailing '/'

or use (Be aware that serving dirs static is not working properly. I have every large file in a single static statement including the ageing
 serveStatic("/", SPIFFS, "/static/index.html");

Not knowing the size of your static files flash with 2MB FS / or 1MB FS / the problem is that if you don't need OTA you always waste space. I created my personal partition schemes with e.g. 2MB Spiffs/2MB flash/No OTA for the prog.
Your memory should be sized as follows prog size + var size (seen in IDE) + size of the largest (static) files * 1.2 (safety margin) should fill "App memory" around 80%. As an example your usage is at the moment as follows:
You have at the moment max 400kb for the app AND serving (static) files. You use

3 MB for SPIFFS file system,
512 for OTA,
min 100kb for your Debug level

=> how could it keep/load e.g a 300kb file into flash?
Your error code 28 is normally connected to out of memory problems, the error message line two indicates that something should be loaded to memory and cant, We ruled out all other reasons so ...

Thats exactly what I have. I know that the files are there and are readable because reading the files individually from SPIFFS works. See my edit above.

I just changed my code to define a file individually but the error is still there :(

Thats a good hint, I will consider adjusting that before deploying. However, my static files (everything inside the data directory) are currently 1,4MB in size. That should be compatible with my current IDE settings, correct?

No its not - you have at the moment max 400kb for the app AND serving static files (you  use 3 MB for SPIFFS file system, 512 for OTA, min 100kb for your Debug level) - how could it keep/load e.g a 300kb file in prgmem -your error message line two indicates that something should be loaded to prgmem and cant We ruled out all other reasons so ...

But if that was an issue, how come handling static file reads not through server.serveStatic() but through server.on(...)with a custom handler function that streams the file over works? See my second edit for reference.

Also, can you maybe provide me with a link to a resource that shows me how to remove the OTA partition space? I just googled for a while and I cant seem to find anything useful...

That would be a new question


text:
New to Arduino and I have a WIP code for a class. ERROR with LEDs working?
(EDIT) My goal with this code is to use two potentiometers, pot0 and pot1 respectively, to control 8 leds. Pot0 controls which sequence the leds are running (1, 2, or 3) and pot1 controls which LEDs within each sequence are active. Currently, I am having a problem because I am running Sequence 1 (the first if statement) to my arduino, but I can't seem to make the LEDs light up when being called out by the potentiometer. The only LED that works is LED 0, and that's only if both potentiometers were in the proper positions when the code begins running.
int pot0 = 0;
int pot1 = 1;
int led[] = {7, 6, 5, 4, 3, 2, 1, 0};

void setup() {

for (int i = 0; i < led; i++){
  pinMode(led, OUTPUT)
;}
}
void loop() {
  int potread = analogRead(pot0);
  int val = analogRead(pot1);
  int potR = map(val, 0, 1023, 0, 7);

if (potread <= 341) {
  for (int i; i == potR;)
  digitalWrite(led[i], HIGH);

}

else if (potread <= 682) {

}
else {

}
}

I actually figured out what was causing the error, but I am now having an issue with what the actual code is doing, so I will update my post

separate the pot reading and the LED lighting ... instead of if (potread <= 341) { digitalWrite(led, HIGH);} use a flag variable .... do something like this if (potread <= 341) level1 = true; ... further down in the program if ( level1 ) digitalWrite(led, HIGH); ... that way your code will be less convoluted

I have updated my post. I would appreciate if you would take another look at it and give me some advice.

you have a malformed for loop

For this, you should be using map(). Instead of int potR = val % 8; try int potR = map(val, [minimum pot value], [maximum pot value], 0, 7). Also, I'm pretty sure you don't need the for loop if all you're doing is led[i]. In that case, you could use led[potR].

I updated my post, thank you for your help. I fixed the For loop issue, and it will now compile to my board. Please read the post for the new issues

This will likely work, but right now I can't really see if it will because I can't get my arduino to stop only lighting leds 6 and 7, and I'm not sure what the issue is. When I run the code, it starts with both of them at a high brightness, and after maybe a second it dims the brightness on LED 6. Is there something in my code that might cause this?

Try some simple troubleshooting like doing a for loop through your LED array.

I managed to figure it out (My arduino was running an old sketch for some reason). Everything seems to be in order except that my pot1 doesn't seem to be affecting which LEDs are lit up, it's only lighting up LED 0 even if I turn pot1 all the way to max.

I spoke to someone the other night while working on this who was able to help me, and have since resolved all of my issues. Thank you to everyone who helped me fix the issues that I was having!
For those interested in how my final code came out ->
int pot0 = 0;
int pot1 = 1;
int led[] = {7, 6, 5, 4, 3, 2, 8, 9};
const int DelayPeriod = 100;

void setup() {
pinMode(pot0, INPUT);
pinMode(pot1, INPUT);
for (int i = 0; i < led; i++){
  pinMode(led, OUTPUT)
;}
}
void loop() {
  int potread = analogRead(pot0);
  int val = analogRead(pot1);
  int potR = map(val, 0, 1023, 0, 7);
if (potread <= 341) {
  for (int i = 0; i <= led; i++){
    if (i == potR){
      digitalWrite(led[i], HIGH);
    }
    else {
      digitalWrite(led[i], LOW);
    }
  }

}
else if (potread <= 682) {
  for (int i = 0; i <= led; i++){
    if (i <= potR){
      digitalWrite(led[i], HIGH);
    }
    else {
      digitalWrite(led[i], LOW);
    }
  }

}
else {
  for (int i = 0; i <= led; i++){
    if ((i <= (potR + 1)) && (i >= (potR - 1))){
      digitalWrite(led[i], HIGH);
    }
    else {
      digitalWrite(led[i], LOW);
    }
  }
}
}

source: Stack Exchange

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

sort: votes


text:
HM-10 BLE controller is not responding to some AT commands
I have HM-10 BLE controller and it is not responding to some AT commands which I need to use.
AT commands which don't work:

AT+TYPE2 returns +TYPE=0
AT+VERR? not responding
AT+VERS? not responding
AT+RESTART not responding
AT not responding but AT+responds with OK
AT+VERSION responding with MLT-BT05-V4.1

The most important command for me is AT+TYPE2 because even if I set pin with command AT+PIN112233, in my Android App, AlertDialog with password field is not activated during connection with bleGatt = bleDevice.connectGatt(this, true, bleGattCallback) function.
I even tried to call createBond() function on this device, but it is not returning anything. I need to activate pairing with password with AT+TYPE2 but its always returning 0 which is default connection without password and pairing method.
I'm not sure if I have some bugged HM-10 controller but I cant even reset it to default settings.
It is working fine with transfering data by characteristics but other stuff is not working.
I've used some weird iterating function to print out AT+HELP commands for this controller and AT+TYPE is not listed there as a command. That means I cant set pairing method? What kind of BLE device has pairing disabled and there is not option to set up at least password?
Here are my commands
21:01:19.739 ->  Command             Description
21:01:19.880 ->  ----------------------------------------------------------------
21:01:19.949 ->  AT                  Check if the command terminal work normally
21:01:20.054 ->  AT+RESET            Software reboot
21:01:20.159 ->  AT+VERSION          Get firmware, bluetooth, HCI and LMP version
21:01:20.271 ->  AT+HELP             List all the commands
21:01:20.365 ->  AT+NAME             Get/Set local device name
21:01:20.459 ->  AT+PIN              Get/Set pin code for pairing
21:01:20.552 ->  AT+PASS             Get/Set pin code for pairing
21:01:20.646 ->  AT+BAUD             Get/Set baud rate
21:01:20.740 ->  AT+LADDR            Get local bluetooth address
21:01:20.880 ->  AT+ADDR             Get local bluetooth address
21:01:20.950 ->  AT+DEFAULT          Restore factory default
21:01:21.054 ->  AT+RENEW            Restore factory default
21:01:21.157 ->  AT+STATE            Get current state
21:01:21.271 ->  AT+PWRM             Get/Set power on mode(low power)
21:01:21.365 ->  AT+POWE             Get/Set RF transmit power
21:01:21.459 ->  AT+SLEEP            Sleep mode
21:01:21.553 ->  AT+ROLE             Get/Set current role.
21:01:21.693 ->  AT+PARI             Get/Set UART parity bit.
21:01:21.787 ->  AT+STOP             Get/Set UART stop bit.
21:01:21.834 ->  AT+START            System start working.
21:01:21.952 ->  AT+IMME             System wait for command when power on.
21:01:22.056 ->  AT+IBEA             Switch iBeacon mode.
21:01:22.161 ->  AT+IBE0             Set iBeacon UUID 0.
21:01:22.264 ->  AT+IBE1             Set iBeacon UUID 1.
21:01:22.381 ->  AT+IBE2             Set iBeacon UUID 2.
21:01:22.475 ->  AT+IBE3             Set iBeacon UUID 3.
21:01:22.569 ->  AT+MARJ             Set iBeacon MARJ .
21:01:22.663 ->  AT+MINO             Set iBeacon MINO .
21:01:22.756 ->  AT+MEA              Set iBeacon MEA .
21:01:22.850 ->  AT+NOTI             Notify connection event .
21:01:22.967 ->  AT+UUID             Get/Set system SERVER_UUID .
21:01:23.071 ->  AT+CHAR             Get/Set system CHAR_UUID .
21:01:23.174 ->  -----------------------------------------------------------------
21:01:23.257 ->  Note: (M) = The command support slave mode only.

use AT+HELP to list the available commands

where did you buy the module?

https://www.banggood.com/KEYES-HM-10-6-Pin-Transparent-BLE-Bluetooth-V4_0-Serial-Port-Module-With-Logic-Level-Translator-p-1023524.html?cur_warehouse=CN

Its weird that it has functional PASS and PIN commands but no way to activate pairing :D

it has some minimal firmware

Probably but I dont know how to update it because I dont know what is firmware version and what kind of firmware will work with this.

same as me... clone of a hm10.
not very much info on this board.
at command doesn't works when they are in caps ..
no need ? or = after command.
you can paired with at+connX (x is the device number, the first founded is 1. the second is 2, etc etc).
it cannot auto connect even if you paired them before.
not much range (7 meter).

As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

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


text:
My LED toggeling doesn't work the way I want
I want to do LED toggeling so I wrote this:
int led=13, button=12;

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

void loop()
{
    // put your main code here, to run repeatedly:
    if(digitalRead(button)==HIGH && digitalRead(led)==LOW)
    {
        digitalWrite(led,HIGH);
    }

    if(digitalRead(button)==HIGH && digitalRead(led)==HIGH)
    {
        digitalWrite(led,LOW);
    }
}

But It doesn't work well, sometimes I need to press the button many times in order to turn on or of...and some times with just one press.
I saw this video but I didn't understand it well:
https://www.youtube.com/watch?v=aMato4olzi8&t=415s
Anyway I don't know why my way doesn't work well.

One word: bounce.

I want to do LED toggeling ... you did not explain how you want the program to function

you fail to realize that loop() repeats 10000 times per second .... you are checking if the button is being pressed, which happens over and over .... you need to wait for the transition between "not pressed" and "pressed" .... that happens only once when you press the button

nice...that helped...thnx

yes right so at the second when button is pressed it tries to make LED on and off the same second

There are a few problems with your approach.

You seem to have the button backwards.  You should wire a button so that it is between the pin and ground.  This way it should read LOW when pressed, not HIGH.  It should also have pinMode(pin, INPUT_PULLUP) instead of INPUT.  With the button wired the way you have it to read HIGH then you will need an extra resistor for each button.  With it wired the right way where it reads LOW then it needs nothing extra.
If the first if statement is true and the button is pressed and it turns on the led, what do you think are the chances that you are fast enough to get your finger off the button in the 62.5 nanoseconds it takes to get to that next if statement?   It's not going to happen, so the button is still pressed there and now the led is on so this line turns it right back off.  Only in the rare case where you happen to get your finger off the button at just the right instant will the led stay lit.  To solve this, look at the "State Change Example" that comes with the IDE.  It shows how to keep track of the last state of the button in a variable so you can act only once when the button actually changes state.
Once you get that worked out you will notice that it seems like for every time you press your button it registers tens of presses.  This is switch bounce.  That's a term you should google.  The contacts are making and breaking contact really fast in the in-between pushed and not-pushed state.  But you need to get the first two issues solved before you worry about bounce.

nice...that helped...thnx

I checked the state change example, but I didnt get why the delay for bounce is used in that specific place ? why to set lastButtonState = buttonState; since button state will anyway return to 0 when button is released , any lastButtonState was 0 anyway..so there is no change in it?

You do that so you can tell when the state changed from on loop to the next.

So the little 50ms delay is there to catch switch bounce.   Do you know what switch bounce is?  When you press a button there is a small period of time where the contacts are almost made and they sort of make and then break and then make and break over and over as they're coming closer together and almost touching.  Then once they touch all the way closed they're closed.  Same thing happens as the switch just starts to open.  So you put a little delay there so that you miss all those rapid changes.

You are right that buttonState will have a 0 when released, but it will have a 1 when pressed.  So the button is not pressed and buttonState and lastButtonState are both 0.  Then you press down the button.  When the button is read now it's HIGH, but lastButtonState is still LOW, now we've detected a change of state.  So we can take some action.  The next time through the button still reads HIGH, but lastButtonState is now also HIGH because we set it to match buttonState at the end of loop.  So nothing happens since they are the same.

And now we are reacting only to the change of state, not constantly doing something as long as the button if HIGH.  That lets us have something happen once per press.
We only react when it first gets pressed.  When you release the button it reads and gets a LOW but lastButtonState is still HIGH, so you can react once to the release if you want and then at the end of loop lastButtonState gets set to buttonState which is LOW now and once again they match.  Once again we have detected the change from HIGH to LOW.

thank you so much...yes got it

so in the example the delay to avoid bouncing is where the if condition is finished....but the bouncing happens when once pressing and once releasing the button, so  to avoid bouncing why is written only out of if and not like this if (buttonState == HIGH)  delay (50)  so it can wait the button to be stable before turning led to on ?

You’re not waiting for the button to be stable.  You’re just taking some time to not read it.  So if the button was low and is now high you know it got pressed.  You can react at that point.  You don’t need to wait until it stops bouncing to react to that.  You need to wait until it stops bouncing to react to anything else, and that’s why we take 50ms off.

Keep in mind that delay isn’t actually about debounce.  It doesn’t do that.  It’s just a hack so you don’t see the bounce.  If you only read a button once every 50 ms you’ll never see it bounce.

aha..ok.. the delay is for reading the button and not to do the digitalwrite, you said above  if the button was low and is now high you know it got pressed. You can react at that point. You don’t need to wait until it stops bouncing to react to that. but in this case the reaction isn't wrong ? because bouncing is a random series of 0 and 1 before the real 1 comes..so the Programm will react to this serie ? or not ?

It just reacts to the first HIGH that it gets.  It doesn’t matter that there is a bunch of bounce behind that.  There’s no other reason you’d be reading HIGH except someone pressed the button.

achso..yes now its clear... thank you so much


text:
DHT11 and Liquidcrystal setting cursor issue
lcd_key = read_LCD_buttons();
float temp = dht.readTemperature();
delay(1000);
// lcd.setCursor(0,0);

if(temp < 0) {
    lcd.print(temp);
}

if(temp >= 0.00 || temp <= 5.00) {
    lcd.setCursor(0,6);
    lcd.print(temp);
    delay(100);
}

Here I got simple code about reading temperature from DHT sensor and lcd but when I raise or lower the DHT's temperature the lcd's cursor always printing my data from 0,0.
I want that when the temperature between 0-5 celcius it shall write data on 0,6 in lcd screen but this code not working.
Thank you for answers.

review the setcutsor() command

I have a feeling you may be using invalid coordinates.
0, 6 means Column 0, Row 6, but most LCDs don't have 6 rows.  Instead I think you want 6, 0 for Column 6, row 0.

I guess it because you use
if(temp >= 0.00 || temp <= 5.00){ // writes over 0 OR under 5 which will always be true for all values measured

and not
if(temp >= 0.00 && temp <= 5.00){   // writes over 0 AND under 5 which you want

the logic error in the OP's code causes temp to always print at (0,6)


text:
Arduino analogRead fluctuates from sensor unless USB connected
I have an Arduino connected to a 4-20 mA sensor through a current to voltage converter. When connected to the power supply the sensor reading fluctuates, as soon as I also connect it to a USB port it stabilizes and gives a correct reading (tested with other reader).
My main code is:
#include <Arduino.h>
#include "Display.h"

#define MINIMUM_DEWPOINT -100
#define MAXIMUM_DEWPOINT 20
#define AVG_READING_SIZE 20

float dewPoint;
uint8_t recordIndex = 0;
uint16_t analogReadingValue[20];
int sensorMin = 0;
int sensorMax = 1023;
int sensorValue = 0;

void setup()
{
    Serial.begin(9600);
    Display::init();

    for(uint8_t i = 0;i<AVG_READING_SIZE;i++)
    {
        analogReadingValue[i] = 0;
    }
}

uint16_t getAvg(uint16_t *arr,uint8_t numberOfElements)
{
    uint32_t sum = 0;
    for (uint8_t i = 0 ; i < numberOfElements ; i++)
    {
        sum += arr[i];
    }
    return  (uint16_t)(sum / numberOfElements);
}

void loop()
{
    analogReadingValue[recordIndex] = analogRead(A0);
    dewPoint = map(getAvg(analogReadingValue,AVG_READING_SIZE), sensorMin, sensorMax, MINIMUM_DEWPOINT, MAXIMUM_DEWPOINT);
    recordIndex++;

    if(recordIndex==AVG_READING_SIZE)
    {
        recordIndex = 0;
    }

    Display::displayDewpoint(dewPoint);
    Serial.println(dewPoint);
    Serial.println(getAvg(analogReadingValue, AVG_READING_SIZE));
    delay(2000);
}

My circuit diagram is:

Vin starts at 6 V https://store.arduino.cc/arduino-uno-rev3

Thank you, i have swapped Vin for the 5v pin, and now it reads at a constant 1023, while retaining the same behaviour when usb connected

If you feed 5V into Vcc (5V), you must not connect USB. ( Or vice versa :) )

That is my goal, however as I pointed out before, the reading i get when it isn't also plugged into usb is the max value of 1023 constantly, which isn't correct

To add to that the 2 power supplies in the diagram are connected to a switch that connects to mains through a cable

You need a decoupling ceramic capacitor between A0 and GND. 100nF should work just fine.

Apparently 5V reference on the 5V pin was the issue as 5V was only supplied to the Vin pin and it was referencing to 0V. Swapping the power supply from Vin to 5V solved the issue


text:
Serial.println using too much memory (not Strings)
I want to feed thousands of analog vibration sensor readings into an array as fast as possible, and then analyze them. Here is my sketch:
const int pSensor1 = A0;
const int aSize=10000;

int a[aSize];

void setup()
{
  pinMode(pSensor1, INPUT);
  Serial.begin(9600);
}

void loop()
{
  for (int i = 0; i < aSize; i++) a[i] = analogRead(pSensor1);

  int RMS = 0;
  for (int i = 0; i < aSize; i++) RMS += pow(a[i], 2);
  RMS = sqrt(RMS/aSize);

  Serial.println("Hello");
}

This compiles and runs fine. My problem arises when I try to change the last line to:
Serial.println(RMS);
I get the error:

Arduino: 1.8.12 (Windows 10), Board: "Arduino Nano, ATmega328P"
Sketch uses 3270 bytes (10%) of program storage space. Maximum is
  30720 bytes. Global variables use 20188 bytes (985%) of dynamic
  memory, leaving -18140 bytes for local variables. Maximum is 2048
  bytes. data section exceeds available space in board Not enough
  memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for
  tips on reducing your footprint. Error compiling for board Arduino
  Nano.

Why does attempting to Serial print a single floating point variable use 985% of dynamic memory?

Probably if you don't print them then the compiler sees that array is never used for anything so it gets optimized away.  It sees that it is useless code that doesn't affect anything and simply removes it.  Once you print it then it actually has to be included in the compiled code.
Think about this.  The Arduino you are using has 2000 bytes of memory.  One int takes 2 bytes.  You want 10,000 of them.  That's 20,000 bytes of memory.  20,000 bytes will never ever fit into 2,000 bytes.  You need to choose a more reasonable number of samples.

That makes sense, thank you.

Re “You need to choose a more reasonable number of samples”: 10,000 is a perfectly reasonable number of samples for an Arduino Nano. However, storing the samples before computing the RMS value is not reasonable.

OK, maybe I should have said that differently.


text:
ADC value changing after changing Timer1 value in program
I'm writing a code where analogRead() reads ADC value from load. After reading ADC value, if it is not in range, I need to manipulate Timer1 value. Which is also getting changed.
But, after changing the Timer value,  if the load value again gets restored, ADC doesn't show the same value again, but shows some other value.
Please refer below code:
#include <TimerOne.h>

int LED = 13;
int IN0 = 12;
int IN1 = 11;
int OUT1 = 10;
int OUT2 = 9;
int OUT3 = 8;
int OUT4 = 7;
//float A0;
//int OUT5 = 6;
const float refvolt = 5.0;
int volts = 0;
byte tempL_flag = 0;
float samples, loadval, avgacs, acsvaluef =0;
float refval = 2.0;
bool lflag=0;
unsigned long count = 0;

void setup()
{
    pinMode(IN0, INPUT);
    pinMode(IN1, INPUT);
    pinMode(OUT1, OUTPUT);
    pinMode(OUT2, OUTPUT);
    pinMode(OUT3, OUTPUT);
    pinMode(OUT4, OUTPUT);
    pinMode(LED, OUTPUT);
    pinMode(A0, INPUT);
    //digitalWrite(OUT3, LOW);
    Timer1.initialize(370000);
    Serial.begin(9600);
}

word ADC_READ(byte sample, byte tim, byte CH)
{
    word adcdata;
    word avrdata;
    word abcdata;
    byte i;

    for(i=0; i<sample; i++)
    {
        adcdata = 0;
        adcdata = analogRead(CH);
        avrdata = avrdata + adcdata;
        delay(tim);
    }
    return(avrdata/sample);
}

void flash_L()
{
    digitalWrite(LED, !digitalRead(LED));
    digitalWrite(OUT4, !digitalRead(OUT4));

    if (digitalRead(OUT4)==1)
    {
        loadval = ADC_READ(10, 10, A5);
        Serial.println(loadval);

        if(loadval < refval)
        {
            Timer1.initialize(185000);
        }
        else
        {
            tempL_flag = 1;
        }
        return;
    }
}

void loop() {

    delay(2000);

    if(digitalRead(IN0)==1)
    {
        Timer1.attachInterrupt(flash_L);
    }
    else if(digitalRead(IN0)==0)
    {
        digitalWrite(LED, LOW);
        digitalWrite(OUT4, LOW);
    }
}

how many times do you want to attach the same interrupt? It starts counitng again at attach. Put attachInterrupt in setup(). And I wouldn't read ADC in interrupt.

Only when input is read, Interrupt is generated. Yes there is ADC in interrupt , I've written a function for sampling. loadval = ADC_READ(10, 10, A5);

I don't see why would be IN0 HIGH only one loop of the loop(). And you never detach the interrupt or set it back to 370000

Let me explain. If high gets to IN0, Timer will be at 370000. Timer Interrupt will occur.  It will read ADC on load. If load is in range 370000 will continue. If not,  185000. But after load is out of range and Timer is at 185000, if load is restored, timer should be back at 370000. But even if load is restored, ADC value changes and is not same as in previous case, So I cannot jump back to 370000. Hope it is clear now.

"If high gets to IN0, Timer will be at 370000." how? "Timer Interrupt will occur" and will do what? the function is not attached to interrupt yet.

@Juraj sir, if you refer code, in setup() timer has been initialized to 370000. IN0 will be high by external switch. You can see in loop(), if IN0 is high, interrupt is attached flash_L is ISR. In ISR LED and Bulb are toggeled. If this doesn't answer your qstn. I think I'm not getting your qstn

IN0 is HIGH, the interrupt gets attached. at next 370000 micros multiple it fires  and from then it fires always again at next 370000 or 185000 microseconds

@Juraj I think I'm unable to understand what you are saying. I'm not getting your question. 370000 will only change to 185000 if load is not in range. If load is back in range after distortion, I'm not getting the same value of ADC that showed before it distorted.

do you understand that the set timer value of TimerOne is a period at which the attached function will be called repeatedly? so you want to attach the interrupt in setup() or detach it in interrupt. do you want it run repeatedly or as one shot?

@Juraj yes i do understand. That means after 370000 microseconds interuupt will be called and I need to write ISR for that. You can see in setup(), I've initialized the timer. in loop the interrupt (flash_L) has been called. after IN0 is high. yes I want to run it repeatedly every time the IN0 is high.

it will run always after next period, once attached. and it will not run 300000 after you attached it. it will run 300000 micros after you initialized the period. so the logic of your sketch doesn't make sense, because you don't understand how TimerOne library works

https://www.pjrc.com/teensy/td_libs_TimerOne.html

OP keeps talking about it getting set back to 370000 but I don't see anywhere in the code where that happens.  Once it gets set to 185000 it will always stay there no matter the load.

@Delta_G yes in code its nowhere getting back to 185000 bcz once load is restored, ADC value not getting back. So I haven't written that part of code. My main aim is to get ADC value restored then need to change timer value

@Juraj Okay thanks for your help. But doing this timer thing right will give correct ADC values? Help me in that if timer and ADC are linked likewise

@Juraj I tried your suggestion, and studies the link you shared. Then initialized timer after IN0 high and YES!! its done. Thank you soo much. :)

It seemed as if the timer1 has something to do with the adc clock,just check the datasheet

ADC doesn't show the same value again

You are not reading the ADC correctly, so ADC_READ() can return
anything. See the comments in the code:
word ADC_READ(byte sample, byte tim, byte CH)
{
    word adcdata;  // not needed
    word avrdata;  // not initialized
    word abcdata;  // not used
    byte i;
    for (i = 0; i < sample; i++)
    {
        adcdata = 0;  // useless
        adcdata = analogRead(CH);
        avrdata = avrdata + adcdata;
        delay(tim);
    }
    return (avrdata/sample);
}

The big issue is avrdata not being initialized. Its initial value is
whatever was left there (in the stack or some CPU registers) by the code
that ran before. The value returned by the function is then hard to
predict and depends on what the rest of the program is doing.
The other remarks I left in the comments are not that problematic,
although they are revealing of some lack of attention to detail. Same
for some badly named variables. Here is how I would implement this
function:
word ADC_READ(byte samples, byte time, byte channel)
{
    word sum = 0;
    for (int i = 0; i < samples; i++)
    {
        sum += analogRead(channel);
        delay(time);
    }
    return sum/samples;
}

Sir, I will try you suggestion. thank you

its not working sir, I tried your code. I think its having problem with timer and ADC function jumping back to 370000 from 185000

@HrishikeshDixit: I am not addressing the timer issue. I am just showing you how to correctly average ADC readings, which the program you posted doesn't do.

Sir, thanks for the suggestion, it did save variable and some lines of code. Thank you!


text:
I want to send the last 10 minute data via bluetooth
This was for photocell data logging for 30 sec intervals, now I want to write a code which commands from the cellphone and sends back the last 10 minute data.
At first I thought if I make an array of 20 buckets and put it in a loop, then send the loop function to android would make it right. But it just sends me continues data. I only want the last 10 minute data of the program.
float sensorvalue[20];

void setup()
{
    // put your setup code here, to run once:
    Serial.begin(9600);

    for (int i = 0; i < 20; i++) {
        pinMode(sensorvalue, OUTPUT);
    }
}

void loop()
{
    // put your main code here, to run repeatedly:
    sendvalues();
    char c;

    if(Serial.available()) {
        c=Serial.read();
        if (c=='t')
            sendvalues();
    }
}

void sendvalues()
{
    for (int i=0 ; i<20 ; i++) {

        Serial.println(sensorvalue);
        sensorvalue   = analogRead(A0);
        delay(30000); //every 30 seconds read data

        if (i>=20) {
            i=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
        }
    }
    Serial.println("***********************************");
}

it reads every 30 seconds. i want to send the last 10 minute data but i'm not sure this is the right way...

you really should format your code ... it is practically unreadable

If you want to get/send last 10 minutes of data; first you(your code) have to know how long the transmit is gonna be, and then you can use millis() function or an RTS chip to define exactly when you want the data to be sent. basically a count down timer, start for example from 20 minutes and when it reached 10 minutes starts sending the data.

Thank you so much. The idea of count down sounds fine, but i have one problem. I should receive the last 10 minute data whenever i send for example "m" from my serial port.

well then start counting whenever you send the letter "m".

I don't want live data and that's the problem. I need the data that was measured 10 minutes before i send the command. it's either confusing or i'm not on the right road...

What you want for this project is called a ring buffer. Before
reading the rest of this answer, I suggest you stop and take the time to
carefully read the Wikipedia page I am linking to.
Did you read it? Good! Now, yours is a somewhat special case in that you
don't need to continuously keep track of both a read pointer and a write
pointer: you only need the write pointer, as the read happens all in one
big batch.
Once your ring buffer is full, you will start overwriting the oldest
readings, those that are more than 10 minutes old. When the program
is instructed to dump the data, it will send out the whole buffer,
starting with the cell pointed to by the write pointer (the cell that
holds the oldest data point and was about to be overwritten).
There is one special case to take care of. What if the program gets the
command to dump the data while it has less than 20 readings stored?
You could decide that this is a user error, and it's OK for the program
to give garbage. I suggest, however, that the program should be able to
detect this situation, and then only send the valid data. For this, it
needs to store a boolean variable in order to remember whether the
buffer has been filled or not.
Here is an implementation I propose for such a ring buffer, together
with the functions for adding an item and for dumping all the data
through the serial port:
const uint32_t READING_PERIOD = 30000;  // one reading every 30 s
const int MAX_READINGS = 20;           // 20 readings = 10 min

int readings[MAX_READINGS];  // ring buffer
uint8_t reding_index = 0;    // next available slot
bool readings_full = false;  // did we fill the ring buffer?

static void register_reading(int value) {
    readings[reding_index] = value;
    if (++reding_index >= MAX_READINGS) {
        readings_full = true;
        reding_index = 0;
    }
}

static void dump_readings() {
    // If the buffer is full, then the next avaiable slot is the oldest
    // reading in the buffer.
    if (readings_full) {
        for (int i = reding_index; i < MAX_READINGS; i++)
            Serial.println(readings[i]);
    }
    for (int i = 0; i < reding_index; i++)
        Serial.println(readings[i]);
}

Now the main program is quite simple. You time the data taken using the
technique shown in the Blink without delay tutorial. You don't want
to use delay() because, when the program is delaying, it cannot
respond to your commands. There is one last question remaining: when it
dumps the data, should it forget it? In other words, if you ask it twice
to dump the data, with less that 10 minutes in between, should it
give repeated data the second time, or should it only provide the fresh
data? In the code below I assume the later option, and thus reset the
buffer, but in the end it is your choice:
void setup() {
    Serial.begin(9600);
}

void loop() {
    // Periodically take a reading.
    static uint32_t last_reading_time;
    if (millis() - last_reading_time >= READING_PERIOD) {
        last_reading_time += READING_PERIOD;
        register_reading(analogRead(A0));
    }

    // Dump the data on command.
    if (Serial.read() == 't') {
        dump_readings();
        reding_index = 0;       // reset the buffer
        readings_full = false;  // ditto
    }
}

thank you so much!!!! I've been stuck in this code forever... I think it was too heavy for a newbie..lol

Can you edit your question to better explain what you want to do?

Your code doesn't make much sense as written.
You need to:
Collect a new value every 30 seconds and save it into an array of values, incrementing a "current value index" variable with each read.
Do you want to trigger the sending of a buffer-full of data when the array is full, or using a command from the remote phone? If you want to trigger the sending from a phone, what would you do if there wasn't a full buffer of data? What would you do if the buffer gets full and there's no command sent from the phone?
Assuming you send a buffer-full of data every time it's available, just wait until the array index reaches the end. When that happens, transmit the entire buffer of data to your phone and reset the array index to start collecting new data.
If you want to trigger sending from your phone you have to handle edge cases like buffer overflow, or trying to send before you have a full buffer of data. I would suggest creating an array larger than you need (say 100 values), making it a ring buffer (google it) and saving new values continuously until the ring buffer is full. If the sketch receives a send command, it could check to see if it has at least 20 values in the buffer, and send those/remove them from the buffer if it does, or send back a "not enough data collected" message if not.

thank you so much :)


text:
RF24 Network. More than one payload
I am using Nrf24Lo1 to communicate a payload of button commands resulting in leds being lit on second. This is working OK.
My aim is to have one as Tx and more than one as RX, I can find several that work in the opposite direction, but none can be adapted. Is it possible to have more than one payload (say "payload2" sent to its own pipe address (Rx)?
//Payload_TX
#include "SPI.h"
#include "RF24.h"
#include "nRF24L01.h"
#define CE_PIN 7
#define CSN_PIN 8
#define INTERVAL_MS_TRANSMISSION 250
RF24 radio(CE_PIN, CSN_PIN);
#define WHICH_NODE 1     // must be a number from 1 - 6 identifying the PTX node

const uint64_t wAddress[] = {0x7878787878LL, 0xB3B4B5B6F1LL, 0xB3B4B5B6CDLL, 0xB3B4B5B6A3LL, 0xB3B4B5B60FLL, 0xB3B4B5B605LL};
const uint64_t PTXpipe = wAddress[0];
const int ip1 = 3;
const int ip2 = 6;
const int ip3 = 15;
const int ip4 = 16;
const int ip5 = 17;
const int ip6 = 18;

//NRF24L01 buffer limit is 32 bytes (max struct size)
struct payload {
  byte button1;
  byte button2;
  byte button3;
  byte button4;
  byte button5;
  byte button6;
};
payload payload;

//struct payload2 {
// byte data1;
//char data2;
//};
//payload2 payload2;

void setup()
{
  Serial.begin(115200);
  pinMode(ip1, INPUT_PULLUP);
  pinMode(ip2, INPUT_PULLUP);
  pinMode(ip3, INPUT_PULLUP);
  pinMode(ip4, INPUT_PULLUP);
  pinMode(ip5, INPUT_PULLUP);
  pinMode(ip6, INPUT_PULLUP);

  radio.begin();
  //Append ACK packet from the receiving radio back to the transmitting radio
  radio.setAutoAck(false); //(true|false)
  //Set the transmission datarate
  radio.setDataRate(RF24_250KBPS); //(RF24_250KBPS|RF24_1MBPS|RF24_2MBPS)
  //Greater level = more consumption = longer distance
  radio.setPALevel(RF24_PA_MIN); //(RF24_PA_MIN|RF24_PA_LOW|RF24_PA_HIGH|RF24_PA_MAX)
  radio.setChannel(108);
  //Default value is the maximum 32 bytes
  radio.setPayloadSize(sizeof(payload));
  //radio.setPayloadSize(sizeof(payload2));
  //Act as transmitter
  radio.openWritingPipe(PTXpipe);
  radio.stopListening();
}
void loop()
{
  radio.openWritingPipe(PTXpipe);
  payload.button1 = digitalRead(ip1);
  payload.button2 = digitalRead(ip2);
  payload.button3 = digitalRead(ip3);
  payload.button4 = digitalRead(ip4);
  payload.button5 = digitalRead(ip5);
  payload.button6 = digitalRead(ip6);
  radio.write(&payload, sizeof(payload));
  Serial.print("Data1:");
  Serial.println(payload.button1);
  Serial.print("Data2:");
  Serial.println(payload.button2);
  Serial.println("Sent");
  delay(INTERVAL_MS_TRANSMISSION);
}`

 // payload Rx
 #include "SPI.h"
#include "RF24.h"
#include "nRF24L01.h"
#define led1 3
#define led2 4
#define led3 5
#define CE_PIN 7
#define CSN_PIN 8
#define INTERVAL_MS_SIGNAL_LOST 1000
#define INTERVAL_MS_SIGNAL_RETRY 250
RF24 radio(CE_PIN, CSN_PIN);
//const byte address[6] = "00001";
const uint64_t rAddress[] = {0x7878787878LL, 0xB3B4B5B6F1LL, 0xB3B4B5B6CDLL, 0xB3B4B5B6A3LL, 0xB3B4B5B60FLL, 0xB3B4B5B605LL };
//NRF24L01 buffer limit is 32 bytes (max struct size)
struct payload {
  byte button1;
  byte button2;
  byte button3;
  byte button4;
  byte button5;
  byte button6;
};
payload payload;
unsigned long lastSignalMillis = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  radio.begin();
  //Append ACK packet from the receiving radio back to the transmitting radio
  radio.setAutoAck(false); //(true|false)
  //Set the transmission datarate
  radio.setDataRate(RF24_250KBPS); //(RF24_250KBPS|RF24_1MBPS|RF24_2MBPS)
  //Greater level = more consumption = longer distance
  radio.setPALevel(RF24_PA_MIN); //(RF24_PA_MIN|RF24_PA_LOW|RF24_PA_HIGH|RF24_PA_MAX)
  radio.setChannel(108);
  //Default value is the maximum 32 bytes1
  radio.setPayloadSize(sizeof(payload));
  //Act as receiver
  radio.openReadingPipe(0,rAddress[0]);
  radio.startListening();
}
void loop()
{
  unsigned long currentMillis = millis();
  if (radio.available() > 0) {
    radio.read(&payload, sizeof(payload));
    Serial.println("Received");
    Serial.print("Button1:");
    Serial.println(payload.button1);
    Serial.print("Button2:");
    Serial.println(payload.button2);
    if (payload.button1 == 0) {
      digitalWrite(led1, HIGH);
    } else {
      digitalWrite(led1, LOW);
    }
    if (payload.button2 == 0) {
      digitalWrite(led2, HIGH);
    } else {
      digitalWrite(led2, LOW);
    }
    if (payload.button3 == 0) {
      digitalWrite(led3, HIGH);
    } else {
      digitalWrite(led3, LOW);
    }
    lastSignalMillis = currentMillis;
  }
  if (currentMillis - lastSignalMillis > INTERVAL_MS_SIGNAL_LOST) {
    lostConnection();
  }

}
void lostConnection()
{
  Serial.println("We have lost connection, preventing unwanted behavior");
  delay(INTERVAL_MS_SIGNAL_RETRY);
}

I am rather old any any help gratefully received.  Thanks for reading.

Just change the address you send to with radio.openWritingPipe(...)...?


text:
Error with led Blinking (avrdude: ser_open(): can't set com-state)
I am new with Arduino and I made something very basic and I don't know why it is not working . I placed the positive led in pin 13 and the negative in GND and wrote this code :
#define LED 13
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

I verified if it 's connected to Arduino Uno and when I upload the code I have this errors :
Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
avrdude: ser_open(): can't set com-state for "\\.\COM4"
An error occurred while uploading the sketch

Sometimes IDE has problems ? What I did wrong ?

Genuine Arduino or a cheap Chinese clone?

I bought a kit from keyestudio

It's this a bad company ?

Starting from https://forum.arduino.cc/index.php?topic=54796.msg2032153#msg2032153 someone seems to have found a solution.

so you didn't use a resistor and shorted the pin to ground with the LED? btw. the Uno has on board LED on pin 13 and Blink example does the same as your sketch

Yes. I followed this tutorial : https://www.youtube.com/watch?v=dnPPoetX0uw

Does this answer your question? avrdude ser_open() can't set com-state

Dp you have some older version of Uno, because R3 doesn't have a resistor on pin 13.

I have the same question on any sketch

You do not have a problem with LED blinking (although there seems a resistor missing for your led), but with uploading a sketch.
Hard test: switch off your computer, remove USB cable, switch on computer, check the COM port appearing when connecting the Arduino via USB cable. Then start IDE and try upload again.
Eventually something else was blocking the COM port.


text:
"undefined reference to SD" with SdFat library
is there any way to rename a file in sd card without using SdFat? Thank you
im getting error when inclung the
    #include <SPI.h>
    //#include <SD.h>
    #include <SdFat.h>
    extern SdFat SD;

the error msg was "Error compiling for board Arduino/Genuino Uno.
"
Local\Temp\ccZn9IeW.ltrans2.ltrans.o: In function FatVolume::init(unsigned char) [clone .constprop.18]': \Arduino\libraries\SdFat\src/FatLib/FatVolume.cpp:439: undefined reference to SD' \Arduino\libraries\SdFat\src/FatLib/FatVolume.cpp:440: undefined reference to `SD'

Looks like you did not add this library the correct way. Please give more information: your IDE, your board, your settings and folder structure of your SdFat library.

The standard arduino sd library can not rename a file. The sdfat library can rename a file. If you want to rename a file, then you have to use the sdfat library.

Remove the extern keyword from SdFat SD; because it tels the compiler that the variable is defined elsewhere and it is not and the linker then can't find it.


text:
DigiSpark USB issue
I installed the drivers for x64 and got this:

Notice it did not install the first one - USBSER.
However, I am able to upload code in the Arduino IDE so I went ahead and uploaded the CDC ECHO sketch and all went well there.
But Windows does not see it as a VCP:

What can I do in order to fix this?

Use this bootloader:
https://github.com/micronucleus/micronucleus
Make sure you have Arduino IDE 1.6.5+
Open the IDE, go to

File > Preference

then find "Additional Boards" URL. Then paste this link and then click OK.
Then go to

Tools > Boards > Boards Manager

and change the type to "Contributed" then install the "Digistump AVR Boards". Then change the Arduino board to the Digispark that you have and you're ready to go!

done all of that. if my posted images would work then it would be better understood.

sry i couldn't help :(

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


text:
Which Arduino board to buy?
I need an Arduino Mega 2560 (that is the one that has more pins). I went to eBay and there are a lot of different boards. I'm thinking of buying an ATmega2560-16AU CH340G MEGA 2560 R3 Board + Free USB Cable for Arduino
. Is this one good? I mean, does it do the work? Is it compatible with the Arduino IDE? Anything I need to know?

This ebay link does not work in all countries. I can't access it from Switzerland.

Could find another link that worked for me: http://www.ebay.com/itm/NEW-ATmega2560-16AU-CH340G-MEGA-2560-R3-Board-Free-USB-Cable-For-Arduino-/151303481964

Thanks that is actually the same but the one im buying is from USA not China its like 2 USD more expensive but its going to take a lesser amount of time to arrive so its good.

Just be aware that the standard Usb drivers do not work. You need the driver mentioned in the listing

Get one with the ATMEGA16U2 instead of the CH340G, if you want full compatibility. The CH340G requires different drivers, but it's pretty easy to install. They will work, just like a regular Arduino Mega. Just know that the quality can be lower that official ones.

The Chinese boards generally work just fine with the official Arduino IDE. One thing to be careful for though is the bootloader. Most the time the Chinese vendor had written a custom bootloader, which may make certain pins behave funny. e.g. a common thing is for pin 13 (the default LED) is permanently high.
I would be very cautious ordering these boards though. Most if not all of these breech the terms of the open source license which Arduino is released under. Besides that, ordering these boards you are supporting the Chinese slave labour gone into manufacturing this board for extremely low prices.
Why not purchase the official Arduino boards? Not only do you get quality boards, but you are also supporting the open source community, and ethically manufactured electronics.

"Why not purchase the official arduino boards?" - well, for starters they are in the price range of Arm boards (and considerably more expensive than the $5 Raspberry Pi Zero and the $9 C.H.I.P., so you're figuratively playing a Pac-Man but paying for an Asphalt 8), besides, there are Arduino clones for $1 (!), so it's hard to justify buying such expensive ramen even if it comes with organic pesto.

The Arduino creators have spelled out their position on clones in a fairly lucid blog post a few years ago.
Your board comes pretty close to being a legitimate clone, but the claims about being manufactured in Italy are almost certainly false and possibly illegal.
I bought a CH340G based board myself, and apart from needing to install a different driver, it's pretty close to the original (There are a few projects that reprogram the 16U2 on a real Arduino board, but the vast majority of projects use the 16U2 as a straight serial converter, and the CH340G seems to do that job OK).
As other answers have pointed out, clone makers don't contribute to the community, so consider buying a real board occasionally. On the other hand, Arduino Mega clones are literally 25% the price of the original, so for that board, going with a clone is certainly tempting.

There is no way to know the quality of the Arduino clones on eBay. They may be fine but you never know.
I recommend buying an official Arduino from one of the official distributors.
There are good quality Arduino compatible boards like the SparkFun Redboard or the Adafruit Trinket. But these are not made to look like official Arduino boards. (Neither of these would work for you since they don't have as many pins as the Mega)

You could buy an official board, but if you're worried about the price, I wouldn't go for the EBay ones. There are other better clones out there. For example, I know that SparkFun makes their own Arduino Uno board, and while it's not called the Uno, it works exactly like it's supposed to, without any surprises. From what I remember, it's cheaper than the official Uno too.

It's a counterfeit, and counterfeits are never a good choice. Scroll this down to the Pricing paragraph to see where your money goes when you buy an official board.

It's not a counterfeit, as it doesn't say it's an Arduino. Not on the board, and not on the listing. The listing only says it's compatible with Arduino shield. Arduino's are open source hardware, so everyone is allowed to make them. Only the the Arduino name is trademarked. Morally though, it would be nice to at least buy one genuine, to show you support of the project.

It may not be a counterfeit but it probably wasn't made in Italy like the image in the eBay listing says.

I bought some of those boards and have had no problems with them.  They are not as some claim, counterfeit boards.  If they were, that would mean that the 'arduino' boards are not open source.  I have also never seen any boards claiming to be built from italy.  They are specifically labeled "Made In China".

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


text:
I2C 2 way communication between Arduino Uno and Arduino Mega
If I remove the transmission code from slave this works properly but I need to transmit from slave.
Here is my master code
#include <Wire.h>
void setup() {
  Wire.begin(3);
  Wire.onReceive(receiveEvent);
}
byte x = 0;

void loop() {
  Wire.beginTransmission(9);
  Wire.write("s");
  Wire.write(x);
  Wire.endTransmission();
  x++;
  delay(500);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    int x = Wire.read();
    Serial.println(x);
  }
}

Here is my slave code:
#include <Wire.h>
void setup() {
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    char c = Wire.read();
    Serial.print(c);
    if(c == 's'){
      int x = Wire.read();
      Serial.println(x);
      //transmit to master
      Wire.beginTransmission(3);
      Wire.write(1);
      Wire.endTransmission();
    } else {
      Wire.read();
    }
  }
}

Is it possible not to use Wire.onRequest(requestCallback); to send data to master? Kindly help.

the Wire.requestFrom has only one wire.write i need multiple wire.write which is not supported so is there any workarounds ?

To join the bus as a master you cannot supply a 7-Bit slave address so your code has two slaves.
Below you will find 2 sketches that successfully sends data to a slave. I would suggest you start looking at the I2C protocol and understand there are 4 Modes:

Master->Transmitter
Master->Receiver
Slave->Transmitter
Slave->Receiver

All communications regardless of how the data is transferred requires a master. It's the master that controls the clock pulses, thats why its always the master that initiates the communcation.
The MasterReader/MasterWriter tutorials on the arduino forum should now possibly start to make a little more sense when understanding those modes.
This code shows how a master sends data to a slave, and then how it requests data from the slave. If we look at this code from the master point-of-view, you can see it essentially says, send this byte to the client (m->t & s->r), then request data from the slave (m->r,s->t)
Master Code
#include <Wire.h>

#define SLAVE_ADDRESS 0x60

void setup()
{
  Wire.begin();
  randomSeed(analogRead(3));
  Serial.begin(9600);
}

byte x = 0;

void loop()
{
  x = random(0,255);
  Serial.print("Sent: ");
  Serial.print(x, HEX);
  Serial.print("\n");
  Wire.beginTransmission(0x60);
  Wire.write(x);
  Wire.endTransmission();
  delay(500);
  Serial.println("Requesting Data");
  Wire.requestFrom(SLAVE_ADDRESS, 1);

  int bytes = Wire.available();
  Serial.print("Slave sent ");
  Serial.print(bytes);
  Serial.print(" of information\n");
  for(int i = 0; i< bytes; i++)
  {
    x = Wire.read();
    Serial.print("Slave Sent: ");
    Serial.print(x, HEX);
    Serial.print("\n");
  }
  delay(500);
}

Slave Code
#include <Wire.h>

#define SLAVE_ADDRESS 0x60
byte x = 0x00;
void setup()
{
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void requestEvent()
{
  Serial.print("Request from Master. Sending: ");
  Serial.print(x, HEX);
  Serial.print("\n");

  Wire.write(x);
}

void receiveEvent(int bytes)
{
  if(Wire.available() != 0)
  {
    for(int i = 0; i< bytes; i++)
    {
      x = Wire.read();
      Serial.print("Received: ");
      Serial.print(x, HEX);
      Serial.print("\n");
    }
  }
}

On master you could scan the address range for connected device. This would be a proper approach.

In both of your event handlers: Don't do serial prints inside an ISR. It may work until the serial buffer fills up, then it will hang.

You don't need to test if(Wire.available() != 0) because the bytes variable has the number of bytes you received. If anything, test if bytes > 0 however I presume that a receive event would have at least one byte.

I went through this problem recently. Your slave needs two functions: one for sending and the other for receiving data.
// function: what to do when asked for data
void requestEvent() {
Wire.write(t);
}

// what to do when receiving data from master
void receiveEvent(int howMany)
{Val = Wire.read();}

Here is a code that works both ways of i2c communication in a single code
Sending and receiving different types of data via I2C in Arduino

You had:
 void receiveEvent(int howMany)
 {
   {
         if(Wire.available()){
           char c = Wire.read();
           Serial.print(c);
           if(c == 's'){
             int x = Wire.read();
             Serial.println(x);

             //transmit to master
             Wire.beginTransmission(3);
             Wire.write(1);
             Wire.endTransmission();

           }else{
             Wire.read();
           }
         }

       }

There are a number of problems with your slave code.

Don't do Serial prints in an ISR (interrupt service routine)
Don't do beginTransmission / endTransmission in a receive event.
Don't do any writes
To send data back use a requestEvent not a receiveEvent.

Better would be:
// add in setup()
Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

...

volatile byte what;

void receiveEvent(int howMany)
{
  if (howMany < 2)
    return;

  char c = Wire.read ();
  if (c != 's')
    return;

  what = Wire.read ();  // remember what we got
}  // end of receiveEvent

void requestEvent()
{
  Wire.write (1);  // return a response
}  // end of requestEvent

the Wire.requestFrom has only one Wire.write. I need multiple Wire.write which is not supported so are there any workarounds?

Batch up the response and do one write:
void requestEvent ()
  {
  byte buf [4] = { 1, 2, 3, 4 };
  Wire.write (buf, sizeof buf);   // send response
  }  // end of requestEvent

Reference
There are a lot of examples at I2C - Two-Wire Peripheral Interface - for Arduino


text:
Can i exchange my arduino nano for an atmega328p-pu in my project?
Im currently trying to make a smart light switcher that is attached in front of my rooms light switches. It basically mostly consists of two servos (to turn on or off either switch), two button (to turn the servo manually), an esp8266 esp-01 module (to be able to use with a google home) and my arduino nano. I really need to make it as small as posible and i also want to keep my only arduino not attached to the wall. Would it work if i use an atmega328p or like an attiny84a to replace the arduino?
Im not finished with connecting the esp-01 to the arduino but i was thinking of using the arduino's 3.3v output pin. Would i need extra components to run the microcontroller on its own?
Im really new to arduino and im trying to learn the most I can and to try to make my little project as good as i can.
Would really appreciate some help please, thank you!

This article might help you. It is specially for the Atmega328p and for setting up the complete Arduino, but it explains all the important things

The 3.3V output is on the board.  You’re not going to get that from the chip   The chip doesn’t have its own regulator.  I doubt the 3V3 pin could push an ESP anyway.  They pull a good bit of current.

ESP-01 could consumed as much as 170mA burst, all the Arduino Boards (I only have Leonardio, Nano and Pro Micro) that I have can't supply enough current for the ESP-01.

I use a Pro Mini with a ESP-01 that sit on a tiny self-made 30x23mm adaptor board which includes a LDO regulator for powering both the Pro Mini and ESP-01. Instead of trying to use bare-bone ATMega328p, just get a Pro Mini, it is probably cheaper and not much bigger than the bare-bone when you add the crystal and other components.

Hi @hcheung, would you mind showing how you made your project or where you found the information of connecting the ESP-01 to a Pro Mini? I decided to buy the board since its smaller but im still not sure how to use the module. Thanks

Pro Mini is just like a Nano, except it does not has the USB interface and you have to use a USB-TTl adaptor to upload Arduino Sketch. For ESP-01, I forked a library that utilising AT Command communication between Pro Mini and ESP-01. But on a recent project, I use a hybrid approach for both ESP-01 and an STM32 boards running Arduino sketch and communicate via serial, you can read about my approach at here.

Sure you can - as long as you include the rest of the support circuitry.
However the ESP-01 beats the Arduino hands-down and can do everything the Arduino does by itself - except it lacks IO so connecting to the servo and button could be tricky.
So using some kind of extra MCU as an IO expansion over serial would be a good idea, but a 328P is rather more than you need. Maybe you should look at something smaller, such as one of the ATTiny chips.


text:
Arduino Hardlid Unlocker
I am trying to build a unlocker on my hardlid for my ute. I have replaced the manual unlocking mechanism with 2 of these https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813.
Now my code below works sometimes and I cannot work out why. The way the code should work is

Press Unlock Button (Count increments)
Press Unlock Button again
When count = 2 turn relay on for 4 seconds then turn off
reset count to 0
If time between presses is longer than 10 seconds reset count to 0

Basic diagram below. Please note the push button is actually wired to a relay which is triggered by the car unlock remote and the LED is the actuators.

This is my code
int switchPin = 2; // choose the input pin (for a pushbutton)
int relayPin = 4; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
int counter = 0;
int currentState = 0;
int previousState = 0;
bool lockOn = false;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

unsigned long LockcurrentMillis = 0;
unsigned long LockpreviousMillis = 0;

const long interval = 10000;
const long Lockinterval = 4000;

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

  pinMode(switchPin, INPUT); // declare pushbutton as input
  pinMode(relayPin, OUTPUT); // declare pushbutton as input

  Serial.println("Ready");
  Serial.print("IP address: ");

}

void loop() {

  currentMillis = millis();
  LockcurrentMillis = millis();
/*
  Serial.print("Current ");
  Serial.print(currentMillis);
  Serial.print(" | Previous ");
  Serial.println(previousMillis);
    //Serial.println(lockOn);

  Serial.print("Lock Current ");
  Serial.print(LockcurrentMillis);
  Serial.print(" | Lock Previous ");
  Serial.println(LockpreviousMillis);
  */
  if (lockOn == true){

    if (LockcurrentMillis - LockpreviousMillis >= Lockinterval) {
      // save the last time you blinked the LED
      LockpreviousMillis = LockcurrentMillis;
      digitalWrite(relayPin, LOW); // turn relayPin off
      lockOn = false;
      Serial.println("relay off");
    }
  }

  val = digitalRead(switchPin); // read input value
  if (val == HIGH) { // check if the input is HIGH (button released)
    currentState = 1;
  }
  else {
    currentState = 0;
  }
  if (currentState != previousState) {
    if (currentState == 1) {
      counter = counter + 1;
      previousMillis = currentMillis;   //reset timer
      Serial.println(counter);
    }
  }
  if (counter == 2) {
    counter = 0;
    digitalWrite(relayPin, HIGH); // turn relayPin on
    //delay(4000);
    //digitalWrite(relayPin, LOW); // turn relayPin off
    lockOn = true;
          LockpreviousMillis = LockcurrentMillis;

    Serial.println("relay on");
  }

  previousState = currentState;
  //delay(250);
  if (currentMillis - previousMillis >= interval) {
    // save the last time you presse the button
    previousMillis = currentMillis;
    //LockpreviousMillis = LockcurrentMillis;
    //if (counter >= 1) {
    Serial.println("Took too long reset count");
    counter = 0;
    lockOn = false;
    //}
  }
}

Any Help would be highly appreciated
Thanks

First thing: debounce the button.

Button debounce library: https://github.com/thomasfredericks/Bounce2

What's a ute?  Have you ever seen the movie "My Cousin Vinnie"?

@Delta_G, lol .... i was thinking the same thing

A ute :) ... https://edge.pxcrush.net/std/car/cil/mxu89gdw4v7sjx3evj47ec64d.jpg?width=900

Your circuit drawing seems very wrong, but it is not helpful since, as
you say, it doesn't represent the real circuit. Please, add a proper
diagram of the actual circuit.
As for your reliability problem, I did not dig into the logic of the
code you posted, but I suspect it may be caused by the lack of
debouncing. You could add you own debouncing code but, for the sake
of simplicity, I suggest you instead use a ready-made library, like
Bounce2.
For the kind of program you are trying to write, I find that the logic
becomes way easier to grasp if you think think of it as a finite state
machine. This is program construct based on the idea that the
system can be in any of a predefined set of possible states, and that
its behavior and the possible state transitions depend on what
particular state it is in. In this specific case, I would use three
states:

In the LOCKED state, the lid is locked and you need to press the
button twice in order to unlock it. Once you press the button once,
it transitions to the WAITING state.
In the WAITING state, the lid is still locked, but the first
button press has already been registered. If you press the button
again, the system transitions to the UNLOCKED state. If not,
after a timeout it transitions back to LOCKED.
In the UNLOCKED state the lid is unlocked. After another timeout it
transitions back to the LOCKED state.

Once you have this logic written down, it can be translated into code in
a very straightforward way:
#include <Bounce2.h>

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 s
const uint32_t lock_interval =  4000;  //  4 s

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // not used in the LOCKED state

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change >= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change >= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}

Thank you Edgar. You code certainly looks much easier to read and follow. I will try you code now and report back.
Thanks Again

This works perfectly! I update schematic also. thanks


text:
How to swap byte order
Background
I'm reading a 24-bit ADC value into a uint32. Using SPI bus, here's the logic:
value = SPI.transfer(0);   // read first 8 bits (MSB first)
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read next 8 bits
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read final 8 bits

As such I'm left with this ADC reading:
00000000 11111111 11111111 11111111
         MSB                    LSB

(Ignore the leading zeros for now.)
Now I transfer this value over ethernet like so:
client.write((const byte*) &value, sizeof(value));

The problem is this:

The value is stored as MS bit first.
client.write() transmits it LS byte first.

I am using NodeRED as a TCP server. So at the other end, I receive the data like this:
11111111 11111111 11111111 00000000
     LSB          MSB

I understand this is the expected behavior, but I would like to switch the BYTE order around before sending, so that it is read in NodeRed native endianness.

Question
Perhaps I should do some bit shifting at the point of reading the ADC, to accommodate the fact that client.write() sends the least significant byte first, like this:
  byte1 = SPI.transfer(0);
  byte2 = SPI.transfer(0);
  byte3 = SPI.transfer(0);
  response = byte3;
  response <<= 8;
  response = byte2;
  response <<= 8;
  response = byte1;

Is this the most efficient way in terms of clock cycles?
Please note that my MCU is a Teensy 4.1, and I'm transferring 10,000 readings per second. I would like to keep the clock cycles for any necessary bitwise operations to a minimum, so that the timing of ADC readings are affected as little as possible.

You can use an array of byte to save the shifts at all. This solution should be the one with the least clock cycles, and with no additional memory usage.
static byte value[4] = { 0 };

    /* ... */

    /* value[0] is still 0. */
    value[1] = SPI.transfer(0);
    value[2] = SPI.transfer(0);
    value[3] = SPI.transfer(0);

    client.write(value, sizeof value);

Some notes:

Using an array avoids the re-interpretation of a 32 bit variable as a byte array. You read bytes from SPI, and write() expects a byte array. This circumvents your endianness issue completely.

In the call of write() you don't need to cast the address of value to const byte *, because the const is a qualifier for the called function. It is not allowed to change the bytes pointed to.

Making the array static saves you from zeroing the first byte repeatedly. BTW, it is sufficient to provide the first byte, as all other bytes are zeroed automatically. However, the last bytes will be updated on each transfer.

sizeof is an operator, not a function. However, it is quite common to use it with a type instead of an object, and then you need parentheses because of the syntax. But it is better to use the respective object, actually you mean that.

You have explained this really well, but just to confirm as I get to grips with this idea, you are saying instead of using an in32_t function and creating a response value, then reading / shifting each byte into the value, it's better to create an array of bytes? So let's say I am storing 100 values, I would have a 2D array (100 x 3 or whatever)? I am sure the answer is "yes" but I just wanted to fully understand.
Also what if I want to cast to float and send that value, with bytes swapped as well? Is it best to read into an array, then somehow cast 3 vals in the array to a float?

// reverse wire order:
client.write((const byte*) &value + 3, 1);
client.write((const byte*) &value + 2, 1);
client.write((const byte*) &value + 1, 1);
client.write((const byte*) &value,     1);

Just nitpicking but... I would add either spaces around + or parentheses around (const byte*) &value. Otherwise it looks like + binds more tightly than the cast, which is of course not the case.


text:
Return a char concatenation
My goal is to create a function that concatenate 2 chars into 1, and return it as MQTT subscribe. I get a difference between the results inside and outside the function ( I'm new to Arduino ), and I can't find why:
Code:
// Update variable below:
const char *direction = "up";
const char* clientID = "Sonoff";

//Consts
const char *client_temp = "HomePi/Dvir/Windows/";
const char* outTopic = "HomePi/Dvir/Messages";
//const char* outTopic2 = "HomePi/Dvir/Windows/ESP32";
const char* inTopic2 = "HomePi/Dvir/Windows/All";
char *inTopic;

void setup() {
  Serial.begin(9600);
//  len(create_topic(client_temp, clientID));
  inTopic = create_topic(client_temp, clientID);
  Serial.println(inTopic);
}

char *create_topic(char *chr1, char *chr2){ .   // added *
  char topic[strlen(chr1) +strlen(chr2)+1];
  sprintf(topic,"%s%s",chr1,chr2);
  Serial.println(topic);
  return topic;
}

void loop() {
  // put your main code here, to run repeatedly:

}

Result ( both line should have been same):
HomePi/Dvir/Windows/Sonoff
⸮⸮,茗⸮;⸮_⸮%⸮l?⸮az⸮z⸮%⸮⸮⸮\;⸮m⸮

You cannot return a local string (e.g. topic) in C. Either use a global variable or a parameter with a reference to a local string in the caller context or use malloc()/strdup().

The concatenation is working fine in both instances.
What is wrong, though, is that you can't return a pointer to a locally declared array from a function. That array no longer exists when you leave the function.
The thing to remember with arrays is that you never pass the actual array to or from a function. All you pass is a pointer to the memory address where the array is.  If you allocate an array in a function that memory is allocated on the stack. When you return the array from the function you return an address that is (currently) within the stack.  When you leave the function all memory allocated on the stack by that function is removed, and that includes your array.
There are four ways of solving the problem - all of them have their pitfalls.

Use a global "scratch pad" array that is big enough for any concatenating you may want to do. Do your concatenation in there.
Declare your array static, which means it's allocated only once and can be returned from the function - but like the global one you have to have a fixed size.
Pass a pointer to a suitably sized array to your function to have that array used for the concatenation, and
Allocate memory on the heap using malloc().

My normal method is number 3. It's the safest and most flexible:
const char *a = "part a";
const char *b = " part b";

char all[14];
doConcat(a, b, all);

void doConcat(const char *a, const char *b, char *out) {
    strcpy(out, a);
    strcat(out, b);
}

can you be more specific for solution 3 ?

And he's using char as the return type instead of char *.

Even worse, OP tries to return a char from a char*. Your solution suggestions are on point, although malloc should b avoided on tiny Arduinos.

@Guy.D , create an array of suitable size before calling the function and just pass a pointer to it. Also look up strcat http://www.cplusplus.com/reference/cstring/strcat/

I tried also with char * - fixing my code

Even returning a char * with your current code the results are still only there by chance and are only temporary. You are accessing memory that isn't yours, and is destined to be overwritten at a moment's notice corrupting your results.

Do an experiment. Run create_topic twice and then try and print both results afterwards. Watch the corruption.


text:
How to store a struct in a file?
I'm trying to store (read&write( a struct using LittleFS on ESP8266.
Appreciate assistance
struct oper_string
{
  bool state;     /* On or Off */
  uint8_t step;   /* Step, in case of PWM */
  uint8_t reason; /* What triggered the button */
  time_t ontime;  /* Start Clk */
  time_t offtime; /* Off Clk */
};

you can think of a struct as an array (group) of variables which might be of a different sizes and struct helps you take specific portion of this string.
Lets say you have a struct of
struct foo{
   bool first;
   uint8_t Second;
   uint16_t Third;
} structMember;

Then it is stored in a row in exactly same order as they have been defined
---------------------------
| bool | uint8_t | uint16_t|
|1 byte| 1 bytes | 2 bytes |
--------------------------
1B+1B+2B = sizeof(srtuctMember)

File.write()
saves date in a file in block of 1Byte each.
When you send array to the function it actualy receives only  a pointer to its beginning.
That is why many functions take a size as a second argument.
When you send a data into a function in a format its not designed to take you can tell the compiler that the function should trait it as a different type of variable.
Lets say we have function defined as
void sampleFunction(byte var1)
then we can use it by
char x='j';
sampleFunction((byte) x);

which tells compiler to treat 'x' as if it was byte.
when you pass array you are not really passing the actual data, but an information where the data is(same with the struct member), so by putting asterisk after the definition you are telling compiler the format of data it points to.
and when you read it back you will get all the contend back as same data in same order... which struct then divides in a same way
file.write((byte*) &StructMember,sizeof(structMember));

I only wish somebody have explained this to me when I was struggling to understand it dealing with char and utf8 few years ago...

So the idea is that each member in this struc is referenced as a byte / utin8_t pointer? and the result is an arrary of pointers (without any delimiter, space or so) ?

@guyd: StructMember is an instance – not a member – of the struct. The idea is that the struct as a whole is to be handled as an array of bytes. More precisely, the address of the struct is to be treated as the starting address of an array of bytes. That is a pointer to an array (of bytes), not an array of pointers.

@EdgarBonet - Sorry for my english, but a member of the struct is for example offtime which is referenced an address (&). Thank you for clearing this out.

Just as a complement to Tomas' answer (which is perfectly valid), I
would like to point out that consecutive members of a struct may not be
adjacent in memory. Some structs have padding within them, which is
needed to satisfy alignment requirements.
The struct given by Tomas as an example will not have padding, but yours
may. For example, on my 64-bit PC, your struct is stored as follows:

offset
size
member

0
1
state

1
1
step

2
1
reason

3
5
(padding)

8
8
ontime

16
8
offtime

In the table above, “offset” is the position of the member relative to
the start of the struct. The padding after reason is needed in order
to align ontime at an address that is multiple of 8. Your ESP
being a 32-bit machine, it is likely to use only a single byte of
padding.
Padding may be an issue for two reasons:

It can differ between computer architectures. Thus, if you plan to
write the file on the ESP and read it back on your PC (or vice
versa), it is one of the possible sources of incompatibility, the
others being endianness and member sizes.

It is a waste of disk space, although this might not be an issue if
you are only loosing 1 byte out of 20.

If padding can be problematic, the only valid option is to write and
read the struct one member at a time. Conversely, if the file is only
ever going to be accessed by the ESP, and you don't mind loosing a few
percent of the file to padding, then don't worry, follow Tomas' advice,
and read and write the struct as an array of bytes: it is just simpler.

thank you for that point of view (which was a hunch I got when commenting on tomas's answer).
I have 3 other files on that ESP ( can be either ESP32 or ESP8266 ), that paramters are stored.
Other option I was thinking of was save it a string file value0;value1;value2... having a delimiter as a marker.
And lasltly, using ArduinoJSON as key/ value pairs, and again save it similiarly to a parameter file I have on board.
What would you recommend ?

Thanks I was intending to refer to padding, as a part or reasoning for using sizeof rather then specific size number, and wanted to point it out in regards to bool, but somehow it got lost in edit attempting not to write too many points. I accept I am a IDYer, and attempt to write mine answers on a simpler level. And thatnks for improving so far all of mine answers here :-) you deseve the editing rights

@guyd: I almost always favor text formats over binary: they are somewhat harder to parse for a computer, but way more convenient for the humans who are going to debug the stuff. Binary is the choice for when you need space efficiency (either in the file itself or the code that handles it) or I/O performance. That being said: all the options you suggest are valid. Pick the format you are most comfortable with.

@Tomas: Thanks! Sometimes I am a nitpicker. Your answers are helpful and valuable contributions, and improving upon something that is already good feels quite rewarding. ;-)

Thank you both for a complete answer!
Guy

one can write a struct directly into a SPIFS/ FFAT file like this:
 * EXAMPLE READING AND WRITING A C++ STRUCT TO A FILE
 */
#include <FS.h>
#include <SPIFFS.h>

typedef struct {
  char someString[10];
  float someFloat;
} MyStruct;

MyStruct myStruct = { "test test",1.7 };

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  if(!SPIFFS.begin()){
      Serial.println("Card Mount Failed");
      return;
  }

  strncpy( myStruct.someString, "testtesttest", sizeof(myStruct.someString) );
  File myFile = SPIFFS.open("/somefile.txt", FILE_WRITE);
  myFile.write((byte *)&myStruct, sizeof(myStruct));
  myFile.close();
}

void loop() {
  // put your main code here, to run repeatedly:
  File myFile = SPIFFS.open("/somefile.txt", FILE_WRITE);
  myFile.read((byte *)&myStruct, sizeof(myStruct));
  myFile.close();
  Serial.printf( "read: %s, %.2f\n", myStruct.someString, myStruct.someFloat );
  delay(1000);
}

the code above is available on this Github Gist.

Nitpick: if the card fails to mount, setup() should abort() rather than return.

I agree. Is missing a few good practice code verifications for that to work flawlessly. Still is a sound code snippet to use.

@MiguelTomás Guessing it'll work the same using LittleFS ?

to be honest, haven't tried it recently.  however, I see no reason why it will not work...

@MiguelTomás - I'm trying to understand why myFile.read((byte *)&myStruct, sizeof(myStruct)); is used (byte *) ? I would have never guessed that syntax

right... i can recommend some good youtube video tutorials, alternatively coursera.org or udemy


text:
Why shouldn't you connect more than one motor directly to either the 5V or 3.3V pins/rails of an Arduino?
Why shouldn't you connect more than one motor directly to either the 5V or 3.3V pins/rails of an Arduino?
What would go wrong otherwise?

In short, the power regulator (or 5V USB) may/can not supply enough current. Overcurrent can cause damage to devices or undefined behaviour.

On an Uno, the barrel jack feeds a reverse polarity diode that can support 1A max, which then feeds a 5V regulator rated for 800mA max (800mA cannot be reached due to lack of cooling - but it does pretty well if barrel jack voltage is kept to 7.5V) which then feeds a 3.3V regulator rated for 150mA.
With too high a voltage or too much current, the 5V regulator either goes into thermal shutdown, or often just severely overheats and fails (sometimes spectacularly).
The 5V can also come from the USB source, which has 500mA PTC resettable fuse, so even less current is available.
So power your motor from another source, and use the Arduino output pins to control a transistor to turn the motor on and off.


text:
Multiplexing HID and serial on ATMega32U4
I designed a custom ATMega32U4 based Arduino Leonardo board. I'm using MHeironimus/ArduinoJoystickLibrary to implement an HID joystick. I need to create also a virtual serial port to send NON joystick data to the USB host (Android device).
If I try to set use the usb serial the joystick device is not recognized.
If I stop the serial the joystick works fine.
This's the code:
#include <Arduino.h>
#include <Joystick.h>

#define JOYSTICK_PERIOD 20

const int BUTTON1_PIN = 4;
const int BUTTON2_PIN = 5;

int x = 0, y = 0, rx = 0, ry = 0, din = 0;
long time1, time2;

Joystick_ Joystick(
  JOYSTICK_DEFAULT_REPORT_ID,
  JOYSTICK_TYPE_GAMEPAD,
  2, 0,
  true, true, false,
  true, true, false,
  false, false,
  false, false, false
);

void setup()
{
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);

  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  Joystick.begin();
  Joystick.setXAxisRange(0, 1000);
  Joystick.setYAxisRange(0, 1000);
  Joystick.setRxAxisRange(0, 1000);
  Joystick.setRyAxisRange(0, 1000);

  time1 = millis();

  Serial1.begin(9600);
  Serial.begin(9600);
}

void SerialEvent()
{
  int _count = Serial.available();

  for(int _i=0;_i<_count;_i++)
    Serial1.write(Serial.read());
}

void Serial1Event()
{
  int _count = Serial1.available();

  for(int _i=0;_i<_count;_i++)
    Serial.write(Serial1.read());
}

void loop()
{
  time2 = millis();

  long _period = time2 - time1;

  time2 = time1;

  if(_period >= JOYSTICK_PERIOD)
  {
    din = (digitalRead(BUTTON1_PIN) << 1) | digitalRead(BUTTON2_PIN);

    x = analogRead(A0);
    y = analogRead(A1);
    rx = analogRead(A2);
    ry = analogRead(A3);

    Joystick.setButton(0, din);

    Joystick.setXAxis(x);
    Joystick.setYAxis(y);
    Joystick.setRxAxis(rx);
    Joystick.setRyAxis(ry);
  }
}

Anyone has hints?

Page not found. Please post your code here, not a link to it.

@Majenko ops the repository is private .. my fault.. I posted the code thnx.

it may be a limitation of android

this may help ... https://github.com/NicoHood/HID

https://github.com/NicoHood/HoodLoader2

@jsotola, HoodLoader is for 16u2 on Uno/Mega


text:
Extending pulses of a square wave signal
My idea is to modify a diesel injection system to increase the fueling into the engine.
The signal to an injector is a series of 0.1-1.5ms pulses. I would like to analyse the pulses and then send out my own pulse to extend some of the injection pulses. I want to do this all in real time.

Is this possible on an arduino? I have never used one before so I'd like to know if it is possible and what product would be suitable.

What kind of diesel engine are you using? Have you looked at the injector waveform with an oscilloscope? If you have "Peak and Hold" style injectors: http://autoditex.com/page/peak-hold-injector-53-1.html, then you may have to replicate the "current limiting" phase of the injector "on time". Please edit your question and add some details about the diesel engine / injector you are using.

Yes, assuming the calculations are not that time consuming.
The Arduino is 16 MHz, so this is in the us scale which is way within limits. I don't know how critical the rise and fall times are, but even that should be possible.
You need some additional circuitry though, because the Arduino itself cannot handle 12V signals. For the input, you need so called level shifting (from 12 V to 5 V), see A-Quick-Guide-on-Logic-Level-Shifting for more explanation.
For the output, you need a 12 V signal (or use a voltage booster to 12V), and a transistor (and probably some resistors) that is connected to the Arduino for the signal and to the 12V and the diesel injection system for the 12V.

Wonderful I'll order a nano and take a look at it!

If it helps, consider upvoting and accepting the answer.


text:
Yet another basic and silly question about C++ strings
I made a sketch like this:
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  char str1[64] = "test with spaces";
  char str2[32] = "test with spaces";

  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

//  if (strcoll(str1, str2)) Serial.println("Equals"); // <-- this won't compile for Arduino UNO { why ??? }
//  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with+spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with++++++++++++++++++++++++++++++++++++spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

}

void loop() {
  // put your main code here, to run repeatedly:

}

bool areEqual(char* string1, char* string2) {
  return ((strlen(string1) == strlen(string2)) && (strstr(string1, string2)));
}

Which produces this:
test with spaces
test with spaces
Different
Different
Different
Equals

test+with+spaces
test with spaces
Different
Equals
Equals
Different

test+with++++++++++++++++++++++++++++++++++++spaces
test with spaces
Different
Equals
Equals
Different

The first comparisson is silly (==), I know. It compares the address of the pointer, not of the string itself. I just put it there to show how hard it is for a programmer who comes from another language to understand such a thing.
The second comparison (strcmp), as the reference says "Compares the C string str1 to the C string str2.", NO, it doesn't. They are exactly the same, except for their pre-specified size. But the strings are equal to my eyes.
The third comparison (strcoll) uses locale to compare the two strings, but how come it says different when they are equal?
The fourth comparison (memcmp), given two pointers to the exact same sequence of characters, why does it say "different"?
The mind blowing part is the comparison "works" when you add as many "+" as you wish to only one of the strings. Isn't a "+" sign also a character?
It's obvious I must be missing something really basic about c++ style strings, but I dare to ask: what is it?
Thanks.

A small remark on nomenclature: The char * kind of strings are called "C strings" (careful when googling that), null- or zero-terminated strings, as they originated in C. In contrast, C++ strings are of type std::string. With these, comparison with the == operates as you expect: it compares strings, not pointers.

The return value of strcmp does not have boolean semantics, as you seem to incorrectly assume.
strcmp is a tri-state comparator, which returns negative, zero or positive value. For equal strings it returns zero, which means that an equality comparison with strcmp should normally look as follows
if (strcmp(str1, str2) == 0) Serial.println("Equals");
else Serial.println("Different");

while your original code actually does the opposite.
There's a moderately widespread ugly habit of writing such comparisons as
if (!strcmp(str1, str2)) Serial.println("Equals");
else Serial.println("Different");

(note the application of ! operator). It works properly, but it has poor readability. Avoid it. For tri-state comparators is a much better idea to spell out the comparison with 0 explicitly.
And you made exactly the same mistake with memcmp. memcmp is also a tri-state comparator, so it should be
if (memcmp(str1, str2, sizeof str2) == 0) Serial.println("Equals");
else Serial.println("Different");

The same applies to strcoll.
P.S. And in fact such zero-terminated strings represented by char[] arrays are called C-style strings, not C++-style strings.

Duhhh. You guys are great. In the end of the day, there was no mystic clouds around the strings, it was all about the results of the functions. Thanks.