text:
Why does the interrupt not work after pressing the button
Implement interrupt processing when the button is pressed, and the very start on the rising edge, the interrupt pin and to which the button is connected 11. Why does the interrupt not work after pressing the button?
#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;
volatile bool buttonPressed = false;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(buttonPin, buttonISR, RISING);
  Serial.begin(9600);
}

void loop() {
  if (buttonPressed) {
    Serial.println("Button pressed!");
    buttonPressed = false;
  }
}

void buttonISR() {
  buttonPressed = true;
}

Model:

The termination on the oscilloscope may be enough to pull down Pin 11.  Consider removing the oscilloscope from Pin 11 and repeating the test. If that works, I'll create an answer with more details and things to try.

Removed the oscilloscope from pin 11, still does not work

Have you tried attachInterrupt instead? https://reference.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/ note the use of digitalPinToInterrupt and that only certain pins on each model can be used as such. If it works, likely a bug in your PinChangeInterrupt.h or what it ties to.

I tried  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING) also does not work

See https://reference.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/ Note that GPIO 11 does NOT appear in the column of the table listing pins that can be used to generate interrupts (except for nano 33 IOT, Zero and the 101) - suggest you use 2 or 3. If you want an interrupt on the RISING edge, use a PULL DOWN resistor. https://www.seeedstudio.com/blog/2020/02/21/pull-up-resistor-vs-pull-down-differences-arduino-guide/  that way pressing the button, rather than releasing the button produces the int. Finally, acknowledge that the button will bounce.

But pin 11 is the PCINT3 interrupt?

Which board are you using? Here is a nice simple example of doing something similar - it may help https://roboticsbackend.com/arduino-interrupts/ (I should have added at least one more board to that list).

I  am using arduino uno, the task is as follows: The button must be connected to the corresponding pin interrupt PCINT3.Does the task mean which pins trigger the PCINT3 interrupt, then it would be possible to connect to 3 or 2 pins

I guess I need to do through Pin Change Interrupts, something like this: void setup() {   pinMode(buttonPin, INPUT_PULLUP);   PCMSK0 |= (1 << PCINT3);   PCIFR |= (1 << PCIE0);      attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, RISING);     Serial.begin(9600); }  but it doesn't work

Sorry, but I can't interpret your task for you. Here is another good reference that may help. https://gammon.com.au/interrupts You will figure it out.

is it possible to do button click tracking via Pin Change Interrupts?

Notice the slight difference between your attachPCINT and in the example. There is extra digitalPinToPCINT, basically you are probably catching radio on some other pin.

@GoodYork, I understand you have not done any of this with real hardware.  That the question is based on an emulation only?  You should have said so in the question.  Please go back end edit your question stating clearly that the question is based only on am emulation.  (If you are wondering why an emulation does not reflect the real world ... perhaps we should start by saying that companies like Atmel (now Microchip) are very unlikely to disclose everything about their processor's design.)

I just tested proper code with some changes:
#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;

volatile bool buttonPressed = false;

void buttonISR() {
  buttonPressed = true;
}

void loop() {
  if (buttonPressed) {
    delay(20);
    buttonPressed = false;

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING);

  pinMode(LED_BUILTIN, OUTPUT);
}

And with attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING); it works flawlessly. Only difference is that digitalPinToPCINT (as every example for PinChangeInterrupt library tries to suggest).
You also tried attachInterrupt + digitalPinToInterrupt with the pin 11, but Arduino Uno has only two external interrupt capable pins D2 and D3. So it couldn't work with D11. It also depends on MCU (see attachInterrupt() reference).
The PCINT is more or less related to the old AVRs like Atmega328 or Atmega2560. And PCINT in Atmega2560 isn't available on all port (it uses ISR per port and it has many ports.
If the proteus simulator is the cause, you can also ommit the ISR (as you are not doing anything big here) and just poll the pin:
const uint8_t buttonPin = 11;
bool buttonPressed = false;

void loop() {
  bool pinHigh = (digitalRead(buttonPin) == HIGH);

  if (pinHigh && buttonPressed) { // button released
    delay(20);
    buttonPressed = false;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  } else if (!pinHigh && !buttonPressed) {
    buttonPressed = true;
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}

Just to amplify on this, digitalPinToInterrupt is for pins D2 and D3 on the Uno (this function returns 0 or 1 respectively) when used with attachInterrupt, however digitalPinToPCINT is for the Pin Change interrupts, which the OP is using.

Why doesn't work for me, I use arduino uno

@GoodYork you have to change:  attachPCINT(buttonPin, buttonISR, RISING); to attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING);  or just try to use my code (It's toggling onboard LED - it has really simple debouncing too)

I copied your code, just replaced LED on with Serial.println and something is not working for me

Maybe wiring issue. Or if you are trying it only in emulator, it's not usually working very well with ISRs

I do it in the Proteus emulator

@GoodYork Please take a photograph of your wiring, and amend your question to include that photograph.

@NickGammon I only have the model that is already attached to the question

I do it in the Proteus emulator - you did not disclose that in your question. Emulators may not faithfully reproduce what happens in real life. Your problem is therefore in the emulator. Try using a real Arduino.

I only have the model that is already attached to the question - if you have an emulator then you don't even have that. I read the question and saw that you claimed you were using an Arduino Uno.

Why doesn't work for me, I use arduino uno - you should have said "I use Arduino Uno in the Proteus emulator". One is a real piece of hardware that behaves in a predictable way that we can all test. The other is a piece of software.

then, it's just not possible to do it in the emulator?

You can do it without interrupts, I'm usually just polling button pins every few milliseconds. Added code without isr

@KIIV  the task is as follows: The button must be connected to the corresponding pin interrupt PCINT3 - they have a task, which is to use PCINT3. The task isn't to solve any real-world problem.


text:
How to make the built-in LED blink with a frequency of 5 Hz using interrupts
The task is: after five clicks on OK, the built-in LED starts flashing with a frequency of 5Hz using an interrupt. After the eighth click on OK, the flashing (and glowing) should stop.Why is flashing not working
bool ledState = false;
volatile bool ledOn = true;

void setup(){
TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0;
  TCNT2 = 0;
  OCR2A = 77;
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 |= (1 << OCIE2A);
 pinMode(13, OUTPUT);
}

void loop(){
 if(button5.buttonPressedCount >= 5 && button5.buttonPressedCount < 8){
    ledState = true;
  }

  if(button5.buttonPressedCount > 7){
    ledState = false;
  }
}

ISR(TIMER2_COMPA_vect){
  if(ledState){
  digitalWrite(13, ledOn);
  ledOn = !ledOn;
  }
}

Why OCR2A = 77;?

The value for obtaining a frequency of 5 Hz with a divider of 1024

Could you please explain, within the question, how you go from “f = 5 Hz” to OCR2A = 77;?

timer will run at a frequency of 16 MHz / 1024 = 15.625 kHz, so desired interrupt frequency = (77 + 1) * 15.625 kHz / 1024 = 5 Hz

This calculation is wrong.

then what should the values be?

15.625kHz / 5 Hz = 3125. So I would set OCR2A to 3125. A value of 77 would be about 203Hz

I set to 3125 if this correct signal: link

Could you use Timer 1 instead of Timer 2?

yes I can, then what values should be set?

On the Uno (ATmega328P microcontroller), timers 0 and 2 are 8-bit only:
they cannot count beyond 255. Timer 1, on the other hand, is 16-bits.
This is the most convenient timer for generating low frequencies.
Speaking of frequencies... One LED period involves two toggles (turn on,
then turn off). Thus, if you want the LED to blink at 5 Hz, the toggle
action should happen at 10 Hz. Given that the CPU is clocked at 16 MHz,
this means you have to toggle the LED every 1,600,000 CPU cycles.
If you set the prescaler to 1,024, you then you have to count
1,600,000/1,024 = 1,562.5 timer cycles. You cannot count a non-integer
number of cycles, but you probably do not care about such accuracy. If
you do care, set the prescaler to 256 and count 1,600,000/256 =
6,250 timer cycles by setting the compare match register to 6,249.
One last issue: keep in mind that, in normal counting mode, the timer
counts up to its maximum value (65,535, or 255 on an 8-bit timer) and
then restarts at zero. If you want it to count only up the value set in
the compare match register, you should choose the appropriate waveform
generation mode: the fast PWM mode that lets you control the TOP value
with OCR1A.

then it should look like this? TCCR1A = 0; TCCR1B = 0; TIMSK1 = 0; TCNT1 = 0; OCR1A = 6249; // Set compare match value for prescaler 256 TCCR1B |= (1 << CS12); // Set prescaler to 256 TIMSK1 |= (1 << OCIE1A); // Enable interrupt on compare match A

@GoodYork: Read the datasheet and see how to set the appropriate waveform generation mode.

like this: TCCR1A = (1 << WGM11) | (1 << COM1A0);   TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS12);   TIMSK1 = (1 << OCIE1A);   OCR1A = 6250;

source: Stack Exchange

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

sort: votes


text:
Modbus rtu data decimal to float conversion

Hi,am trying to communicate with power-factor controller [Selec APFC 148-312] using modbus RTU,am following example sketch from modbusmaster library. am able to get the raw data from the instrument but data structure seems to be in decimal format, can someone help me to convert this into float.thank you
#include <ModbusMaster.h>

#define MAX485_DE      3
#define MAX485_RE_NEG  2

// instantiate ModbusMaster object
ModbusMaster node;

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode

  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  // Modbus communication runs at 9600 baud
  Serial.begin(9600);

  // Modbus slave ID 1
  node.begin(1, Serial);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  float result;

  result = node.readInputRegisters(0x30000, 10);
  if (result == node.ku8MBSuccess)
  {

    Serial.print("V1N: ");
    Serial.println(node.getResponseBuffer(0x01));

    Serial.print("V2N: ");
    Serial.println(node.getResponseBuffer(0x02));

    Serial.print("V3N: ");
    Serial.println(node.getResponseBuffer(0x03));

    Serial.print("Vavg: ");
    Serial.println(node.getResponseBuffer(0x04));

    Serial.print("V12: ");
    Serial.println(node.getResponseBuffer(0x05));

    Serial.print("V23: ");
    Serial.println(node.getResponseBuffer(0x06));

    Serial.print("V31: ");
    Serial.println(node.getResponseBuffer(0x07));

    Serial.print("L-L avg: ");
    Serial.println(node.getResponseBuffer(0x08));
  }
  delay(1000);
}

C++ programming question ... not Arduino specific really

decimal format and floating point format are two different things ... what do you actually need?

@jsotola i just need the output displayed in the serial monitor to be in voltage and other parameter readings as given on the data sheet.

Re “data structure seems to be in decimal format”: It's not. It's binary. The reason you see decimal on the serial console is because Serial.println() converts its argument to decimal, for the purpose of printing it as text. The authors of this method assumed that most humans prefer reading decimal rather than binary. Note that Serial.println() can be told (by a second argument) to use a different base.

I'm not sure this can really be considered topical, but someone wanting to read floating point numbers over MODBUS with an Arduino might get something out of it.  Also I have no way to test this really.  But here goes:
Your MODBUS map shows V2N at 30002, and you notice 30003 is not mentioned in the map.  Your voltage from phase two to neutral appears to be encoded into two consecutive 16-bit registers, which is a somewhat normal scheme for conveying 32bit floats via MODBUS, from what I can tell.  So, your values of 17280 and 9830 are two halves of a 32-bit floating point number.  In hex, 0x4380 and 0x2666.  These seem to be taken together as 0x43802666 as the bit pattern for 32-bit float.
A function like this would allow you to extract your 32-bit float data from your separate 16-bit MODBUS register reads:
float modbus_16bit_register_pair_to_float(uint16_t a, uint16_t b) {
    uint32_t combined = ((uint32_t)a << 16) | b;
    float f;
    memcpy(&f, &combined, sizeof f);
    return f;
}

There are lots of ways you could do this.  This code assumes that the float type's endian matches the uint32_t type's endian, and that float is 32-bit, which is common but not strictly standard.
Running this on 17280 and 9830 gives 256.3 (rounded), which doesn't perfectly match other output, but I suspect that's just because the reading is varying.

Thank You Sir. it worked.

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


text:
ESP 32 unable to connect to https website and return the data using GET
I have created a ThingHTTP below:
https://api.thingspeak.com/apps/thinghttp/send_request?api_key=BVLJ7A6KNK9VVAYK

In my browser I could see the reply. But I am unable to make this work in my ESP32. I understand that this is a https so I would have to declare the root cert details. I have tried to modify based on this tutorial:
https://github.com/witnessmenow/arduino-sample-api-request/blob/master/ESP8266/HTTP_GET/HTTP_GET.ino

My code as follows:
#include <WiFi.h>
#include <WiFiClientSecure.h>

//------- Replace the following! ------
char ssid[] = "SSID";       // your network SSID (name)
char password[] = "pass";  // your network key

// For Non-HTTPS requests
// WiFiClient client;

// For HTTPS requests
WiFiClientSecure client;

// Just the base of the URL you want to connect to
#define TEST_HOST "https://api.thingspeak.com/apps/thinghttp/send_request?api_key=BVLJ7A6KNK9VVAYK"

const char *server_cert = "-----BEGIN CERTIFICATE-----\n"
                                  "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n"
                                  "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n"
                                  "VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n"
                                  "DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n"
                                  "ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n"
                                  "VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n"
                                  "mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n"
                                  "IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n"
                                  "mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n"
                                  "XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n"
                                  "dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n"
                                  "jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n"
                                  "BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n"
                                  "DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n"
                                  "9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n"
                                  "jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n"
                                  "Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n"
                                  "ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n"
                                  "R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n"
                                  "-----END CERTIFICATE-----\n";

void setup() {

  Serial.begin(115200);

  // Connect to the WiFI
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  //--------

  // Checking the cert is the best way on an ESP32
  // This will verify the server is trusted.
  client.setCACert(server_cert);

  // If you don't want to verify the server
  // Unlike the fingerprint method of the ESP8266 which expires frequently
  // the cert lasts years, so I don't see much reason to ever
  // use this on the ESP32
  // client.setInsecure();

  makeHTTPRequest();
}

void makeHTTPRequest() {
  delay(5000);
  // Opening connection to server (Use 80 as port if HTTP)
  if (!client.connect(TEST_HOST, 443))
  {
    Serial.println(F("Connection failed"));
    return;
  }

  // give the esp a breather
  yield();
  client.connect(TEST_HOST, 443);
  // Send HTTP request
  client.print(F("GET "));
  // This is the second half of a request (everything that comes after the base URL)
  client.print(""); // %2C == ,
  client.println(F(" HTTP/1.1"));

  //Headers
  client.print(F("Host: "));
  client.println(TEST_HOST);

  client.println(F("Cache-Control: no-cache"));

  if (client.println() == 0)
  {
    Serial.println(F("Failed to send request"));
    return;
  }
  //delay(100);
  // Check HTTP status
  char status[32] = {0};
  client.readBytesUntil('\r', status, sizeof(status));
  if (strcmp(status, "HTTP/1.1 200 OK") != 0)
  {
    Serial.print(F("Unexpected response: "));
    Serial.println(status);
    return;
  }

  // Skip HTTP headers
  char endOfHeaders[] = "\r\n\r\n";
  if (!client.find(endOfHeaders))
  {
    Serial.println(F("Invalid response"));
    return;
  }

  // This is probably not needed for most, but I had issues
  // with the Tindie api where sometimes there were random
  // characters coming back before the body of the response.
  // This will cause no hard to leave it in
  // peek() will look at the character, but not take it off the queue
  while (client.available() && client.peek() != '{')
  {
    char c = 0;
    client.readBytes(&c, 1);
    Serial.print(c);
    Serial.println("BAD");
  }

  // While the client is still availble read each
  // byte and print to the serial monitor
  while (client.available()) {
    char c = 0;
    client.readBytes(&c, 1);
    Serial.print(c);
  }
}

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

}

the program was able to compile, and was able to run until it shows it connect to the network. But then it returned "Connection failed!" I believe it stuck at this line :
if (!client.connect(TEST_HOST, 443))

I am not sure what is the problem here. Comments appreciated.

Try creating a properly formatted HTTP request. Try also connecting to a server not a web page. There are so many things wrong with your GET request I don't know where to start...

Things wrong with your GET request (which are nothing to do with Arduino - just learn the basics of the protocol you are trying to use before you use it):

You are trying to open a socket to a URL not to a server. That can never work. Connect to the server instead (hint: the server, or "FQDN", is the bit between the https:// and the next /).
You aren't providing any path in your GET request, only a comment that says what you should provide.  Hint: the path is everything that comes after (and including) the / following the FQDN.
Your Host: header should contain just the FQDN, not the whole URL. By now you should know what the FQDN is.
You should also include Connection: close in your headers to inform the server you won't be keeping the socket open.

Correct those problems and you might begin to see something useful happening.

Thanks for the pointers. Been new to this. Guess I have started at the wrong place. Anyhow after implementing what you have said, and other minor mistakes, it seems to be working. I found out that I have to change the certificates for the website, there are a few types. Anyway thanks again.

The piece of code below is from a firmware code I've been programming lately to use on Tensilica's Xtensa LX6/7 compatible MCUs (ESP32). The code below makes an HTTPS request using WIFIClientsecure library.
String GetInfoFromDataverse(String url) {
  //Check WiFi connection status

  if(WiFi.status() != WL_CONNECTED){
    mserial.printStrln("WiFi Disconnected");
    if (connect2WIFInetowrk()){
      GetInfoFromDataverse(url);
    }
  }

  int str_len = SERVER_URL.length() + 1; // Length (with one extra character for the null terminator)
  char SERVER_URL_char [str_len];    // Prepare the character array (the buffer)
  SERVER_URL.toCharArray(SERVER_URL_char, str_len);    // Copy it over

  client.stop();
  client.setCACert(HARVARD_ROOT_CA_RSA_SHA1);

  if (!client.connect(SERVER_URL_char, SERVER_PORT)) {
      mserial.printStrln("Cloud server URL connection FAILED!");
      mserial.printStrln(SERVER_URL_char);
      int server_status = client.connected();
      mserial.printStrln("Server status code: " + String(server_status));
      return "";
  }

  mserial.printStrln("Connected to the dataverse of Harvard University");
  mserial.printStrln("");

  // We now create a URI for the request
  mserial.printStr("Requesting URL: ");
  mserial.printStrln(url);

  // Make a HTTP request and add HTTP headers
  // post header
  String postHeader = "GET https://" + SERVER_URL + url + " HTTP/1.1\r\n";
  postHeader += "Host: " + SERVER_URL + ":" + String(SERVER_PORT) + "\r\n";
  //postHeader += "X-Dataverse-key: " + API_TOKEN + "\r\n";
  postHeader += "Content-Type: text/json\r\n";
  postHeader += "Accept: text/html,application/xhtml+xml,application/xml,application/json,text/json;q=0.9,*/*;q=0.8\r\n";
  postHeader += "Accept-Encoding: gzip,deflate\r\n";
  postHeader += "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
  postHeader += "User-Agent: AeonLabs LDAD Smart DAQ device\r\n";
  postHeader += "Keep-Alive: 300\r\n";
  postHeader += "Connection: keep-alive\r\n";
  postHeader += "Accept-Language: en-us\r\n";

  // request tail
  String tail = "\r\n--" + boundary + "--\r\n\r\n";

  // content length
  int contentLength = tail.length();
  postHeader += "Content-Length: " + String(contentLength, DEC) + "\n\n";

  // send post header
  int postHeader_len=postHeader.length() + 1;
  char charBuf0[postHeader_len];
  postHeader.toCharArray(charBuf0, postHeader_len);
  client.print(charBuf0);

  mserial.printStrln("======= Headers =======");
  mserial.printStrln(charBuf0);
  mserial.printStrln("======= End of Headers =======");

  // Read all the lines of the reply from server and print them to mserial
  String responseHeaders = "";

  mserial.printStr("Waiting for server response...");
  long timeout= millis();
  long ttl=millis()-timeout;
  while (client.connected() && abs(ttl) < 30000) { // 30 sec.
    ttl=millis()-timeout;
    responseHeaders = client.readStringUntil('\n');
    if (responseHeaders == "\r") {
      break;
    }
  }
  if (abs(ttl) < 30000){
    mserial.printStrln("OK");
  }else{
    mserial.printStrln("timed out.");
  }

  String responseContent = client.readStringUntil('\n');
  client.stop();

  return responseContent;
  }


text:
Replace CH340 With FTDI
I have built a arduino midi octapad with a Clone of arduino nano that contain a ch340 chip but hairless midi says FTDI driver doesn't installed i installed that driver but it still show that error so can i replace the ch340 chip with a FTDI chip to resolve this Problem... ?

yes ... install an FTDI  chip to resolve the "no FTDI chip installed" error

You can't just take one chip off and put another on. The two are very different things. Like taking a boot off and trying to put a glove on your foot instead. You could remove (or disable) the CH340 and connect an FTDI cable or dongle to the TX/RX pins though. Would that solve the "problem"? Maybe - who knows? What's "hairless midi"?

Personally I wouldn't bother messing with it. I'd just choose a microcontroller with a native USB connection that is capable of being programmed to appear as a USB MIDI device.

When you search for "FTDI" in one of the hairless-midiserial repos on github (I looked at this and this one), you find what looks like your error message (though you didn't actually put it in your question:
./src/PortLatency_win32.cpp:        emit debugMessage("FTDI drivers don't seem to be installed. Not attempting any FTDI latency tricks.");

Also the repos have a class in PortLatency.h with the description:
A simple class to manage latency reduction of FTDI-based serial ports.

This gives us some information:

The message above is not an error message, but a debug message. It might work despite not having an FTDI
The class description suggests, that the program wants to use some tricks to reduce the latency in the communication. These tricks seem to be FTDI specific. When the above debug message appears, these tricks are not used. Thus your performance may be significantly worse than with an FTDI chip. Also one of the repos has an open issue about problems with the CH340, which states, that it just doesn't work correctly. It was updated in May and still has no solution. I would not bet on getting help there. (Also the ground repo, that the other was forked off, wasn't updated since 5 years.)
You cannot fix that debug message by installing the FTDI drivers, because you don't use an FTDI chip.

As we are on Arduino SE here, we cannot really help you with that program running on your PC.
Of course you can use an extra FTDI chip/board and connect it to the RX and TX lines of the Arduino (not using the CH340 USB serial chip on the Arduino itself). But I support Majenkos comment about just migrating to an Arduino with native USB connection (means the USB communication is done by the Arduinos microcontroller directly, not by an extra chip) (for example the Micro, but there are a lot more Arduinos with native USB). That enables you to manipulate the type of USB connection, thus you can let the Arduino directly appear and work as an USB midi device. Then you don't need the hairless-midiserial program anymore.


text:
Use same pin for two purposes
I have only one pin available and I'd need to use it both for a digitalRead and for sending serial messages (assigning it the Tx role within a SoftwareSerial). I can alternate these two operations, but I don't seem to succeed. I could be interested in other pairs as well (digitalRead+Rx, digitalWrite+Tx and digitalWrite+Rx) and I hope that understanding one will solve them all, but for now I'd be happy to get the first one working. My first naive attempt would be something like:
 #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

void setup() {

  pinMode(6, INPUT_PULLUP);

}

void loop() {

  val = digitalRead(6);

  delay(2000);

  swSerial.begin(19200);
  swSerial.print("myData");
  swSerial.end();

  delay(2000);

}

But I've made other experiments, for example with a digitalWrite, hoping that combining two forms of output would be feasible, but again no way. I know I can alternate a pin role between output and input as long as common digital read/write operations are involved, but SoftwareSerial appears to be less flexible. It seems to me it refuses to work as soon as the pin is declared/used for common digital purposes. Is there a way to accomplish my goal?
I guess that similar requirements and fixes (make a pin role more flexible) led to the Software Serial with Half Duplex library, but I'd refrain from adopting it because I feel it is overcomplicated and seems like overkill for my purpose, moreover it doesn't seem actively supported.
To avoid a XY problem, my very initial need (I may have further ones, requiring the different pairs mentioned at the beginning) would be to check whether this pin is floating or connected to something (I can chose between Vcc or Gnd, setting up the pull-up or an external pull-down accordingly) and to send back some information (obviously this is useful if the pin is actually connected, but I have no reason not to send data anyway) alternating the tasks a few times per second at least.

why do you have only one pin available?

Check out my answer to your previous post of this question.

@jsotola it's an hardware-driven requirement

Before trying to write the software, invent the method how the external hardware can differentiate between both purposes. For example, if you want to read a digital value, the external hardware drives the wire. How do you control it to release the wire so that the Arduino can drive the wire? And, how do you control the hardware driven by TX that only during sending it shall read the value on the wire, and not during the time the Arduino reads the other device? Please [edit] your question and add this important information.

@Gil What are you talking about? I'd guess there is a similar question I couldn't find when posting mine (it would be nice to have a link to it) and you assumed I asked twice hiding my identity, which is somewhat disrespectful (considering that I have a decent profile on other SE)

@thebusybee Suppose I have my pin with pull-up enabled. My idea is to have the external hardware to have a stronger pull-down, so that I can recognize it being attached finding my pin driven to LOW. Yet the external hardware stays ready to ready my data

OK. But this LOW would be interpreted as a start bit (and depending on the duration of the LOW and the used baud rate as additional data bits) on the TX line. How do you prevent this?

If I did the opposite? My pin waiting on LOW, the external one driving it to HIGH, then I swap my pin to serial and start transmission Or maybe I could set SoftwareSerial to work with inverse_logic (I'm not sure if this means a low idle too)

From your comments it seems to me, that you only have one external hardware connected to the pin, but you want to first check for its presence before sending data to it. Is that correct, or do you have multiple different hardware connected to that pin?

@chrisl Correct, only one external hardware! Arduino needs to know when this is connected, while it (when connected) needs to receive data from the Arduino. I have no problem sending data in any case (obviously it will be received only when there is connection) but Arduino needs to know when the external hardware is present. Checking if the information is correctly received wouldn't harm, but it's not necessary.

Is it hardware that you build/program yourself or hardware that will give an answer if you send it fitting data? Normally one would just use a simple handshaken meaning that your Arduino send a simple command and listens for the answer. If no answer is received there is nothing connected and you can try again later. Would that fit for you?

Yes, definitely! It's even more than needed! I will probably have a chance to drive the choice of the external hardware, it may be another Arduino. That was the idea behind the Serial with Half Duplex possible solution. I may need to be able to repeat the same principle more than once (n pins, brought in separate locations, each one having the need to sense if ITS hardware is connected). And I'd feel more comfortable with a robust solution, not an almost experimental library that hardly I'd be able to debug...

I still don't understand why the question is downvoted...

First of all, for using the Software Serial you need to set your tx and rx pins to OUTPUT, that what the library does under the hood.
What you may try to do is to set a millis timer (forget about delay(), never ever use it) and change pin mode to INPUT once every 200ms let's say. And after your measurements put it back to output as soon as you can.
200ms delay is normally ok for some readings like button click. If you can read the value more rare do it (for example you may read some sensor value only once per hour). Here is an example:
    #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

byte timer = 200; // Read value every 200ms
uint32_t prevTime = 0;

void setup() {

    // Don't change pin mode here
    swSerial.begin(19200);

}

void loop() {

    if (millis() - prevTime > timer) {
        // you could try swSerial.flush(); here...
        prevTime = millis(); // reset timer
        pinMode(6, INPUT_PULLUP); // changing pin mode and reading value
        val = digitalRead(6);
        pinMode(6, OUTPUT); // changing pin mode back
    }

    swSerial.print("myData");
    // swSerial.end(); // I don't think you need this line;

}

It may be a solution from a programming point of view. But another task is to organize an electric multiplexing for 2 different devices on the same pin as was mentioned by @the busybee

I'll try this straight away!

It works! Thank you! Let me ask you this: are you sure that tx AND rx need pins set to output? It seems to me that the setRX method (line 282 here: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp) called by the constructor sets the rx pin as input, as one would guess. If I wanted to alternate digital read and swSerial read, cannot I leave the pin mode untouched? (apart from pull-ups). I didn't succeed at my first attempt, but I had only a few minutes left and I may have mistaken something else.

As I thought, I just had to debug the code, now it works also alternating digital and serial readings, no need to change the pin's destination: the rx pin has to be input. Thank you!

You're right, Rx (receiver) is INPUT, but Tx (tranceiver) is OUTPUT. You can leave th Rx pin untouched, and change only the mode of Tx pin. BUT!!! You need to be sure that the value you're reading is not from the Serial. You will need serial.flush, some timing or even maybe some physical solution on diods and transistors. It depends on your exact task and conditions.


text:
Why doesn't the Micro OLED library compile on my DUE?
I have an Arduino DUE and just got a Micro OLED display from SparkFun.
Using their library, when I try to compile I get the error below.  Other example code works just fine and I've programmed this thing a million times with my code.  So it's clearly in the SparkFun code.
Here is the SparkFun tutorial page with a description of the product:
https://learn.sparkfun.com/tutorials/micro-oled-breakout-hookup-guide?_ga=1.19136059.2055231411.1404437767
Here is the library I am using:
https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
Here is the error I get:
Build options changed, rebuilding all

/Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp: In member function 'void MicroOLED::spiSetup()':

/Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:46:10: error: cannot convert 'RwReg* {aka volatile long unsigned int*}' to 'volatile uint8_t* {aka volatile unsigned char*}' in assignment
    ssport  = portOutputRegister(digitalPinToPort(csPin));
            ^
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:48:51: error: 'portModeRegister' was not declared in this scope
    ssreg  = portModeRegister(digitalPinToPort(csPin));
                                                     ^
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp: In member function 'void MicroOLED::i2cSetup()':
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:84:2: error: 'TWBR' was not declared in this scope
    TWBR = ((F_CPU / I2C_FREQ) - 16) / 2;
    ^
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp: In member function 'void MicroOLED::parallelSetup()':
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:109:10: error: cannot convert 'RwReg* {aka volatile long unsigned int*}' to 'volatile uint8_t* {aka volatile unsigned char*}' in assignment
    ssport  = portOutputRegister(digitalPinToPort(csPin));
            ^
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:111:51: error: 'portModeRegister' was not declared in this scope
    ssreg  = portModeRegister(digitalPinToPort(csPin));
                                                     ^
  /Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:114:10: error: cannot convert 'RwReg* {aka volatile long unsigned int*}' to 'volatile uint8_t* {aka volatile unsigned char*}' in assignment
    wrport  = portOutputRegister(digitalPinToPort(wrPin));
            ^

/Applications/Arduino.app/Contents/Resources/Java/libraries/SFE_MicroOLED/hardware.cpp:119:10: error: cannot convert 'RwReg* {aka volatile long unsigned int*}' to 'volatile uint8_t* {aka volatile unsigned char*}' in assignment
    rdport  = portOutputRegister(digitalPinToPort(rdPin));
            ^
  Error compiling.

That library is uses some AVR specific methods, that aren't implemented for the ARM processor in the Due.

Ah, that makes sense.  If you want to put this as an answer I will accept.  Thanks

That library is uses some AVR specific methods, that aren't implemented for the ARM processor in the Due.
I don't see a real easy way to port those methods.

This sucks because the DUE has a ton of RAM, 3.3v native so no converters, and is super fast.  Would make an awesome mini-OLED console.  :-)  And yes, I'm old enough that 96K is a lot of RAM.  lol

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


text:
CRC8 code not working properly
I need to send a string followed by its CRC8, 0x31 polynomial (= X^8 + X^5 + X^4 + 1), I've coded this successfully after some troubles, but it doesn't seem to work properly when I check the results.
I used some online CRC calulators so check if my results are fine, but I don't get the same results, no matter what I try.
In fact, differents CRC calculators are not giving me the same results, which troubles me...
Here are my trials on online CRC calculators, always using :
CRC8, polynomial 0x31, data = TEMPS; (beginning of my string)
On http://www.sunshine2k.de/coding/javascript/crc/crc_js.html :

On https://www.lddgo.net/en/encrypt/crc :

On http://zorc.breitbandkatze.de/crc.html :

It doesn't seem normal to get different results when the entry parameters are the same, it confuses me a lot. Am I missing something ?
No matter what I try, I don't get any of these results with my own code.
Here is my code about CRC calculation, using RobTillaart's CRC library (https://github.com/RobTillaart/CRC):
   String crcData = "TEMPS;";
  int crcDataLength = crcData.length();
  char arrayForCrc[crcDataLength+1];
  crcData.toCharArray(arrayForCrc, crcDataLength+1);

  crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

The hex result of this code sample is 0xBA (186 decimal)
I verified every input parameters with gets and prints, they're all correct :
arrayForCrc = "TEMPS;"
polynomial = 0x31
StartXOR = 0
EndXOR=0
ReverseIn=false
ReverseOut=false
Help would be greatly appreciated as I'm stuck and don't know what to try anymore.
Thank you :)

I could explain it if you were getting 0xB5 but not 0xBA. It helps to have completely compilable code.

I just filled out your code with guesses to the point where it compiled with the latest version of that library and I have it is printing 0xB5 and not 0xBA. So either we're both confused or you've got the wrong number in your question.

Check your sunshine screenshot again, because if I put exactly what you have into it and calculate I don't get 0x6E; I get the expected 0x49. Regarding the 'lddgo' screenshot test, it's not really valid. The reverse settings are on. Once you get 0x49 correctly on the sunshine one, turn on both reflect options and you'll see you now get a 0x73 that matches what you have in the lddgo one. So, I'd remove it because this has nothing to do with the problem you're having with the library.

The hex result of this code sample is 0xBA (186 decimal)

Not so far as I can tell; it's 0xB5, which is expected for a simple reason that you'll see. And when modified slightly it matches the 0x49 value. I'm inclined to trust that your code is correct, so far as you've shown it, but your report of what's doing is not correct.

I verified every input parameters with gets and prints, they're all correct

Well, no. As I mentioned in a comments on the question, I get the expected 0x49 on the first site you mentioned with the correct settings. I'm not sure why you're showing 0x6E. But guess what happen if I hit enter after "TEMPS;"? 0x6E. The newline character matters. Also, I do get a 0xBA if I use the correct input but fail to set CRC8 to custom and change 0x07 to a 0x31 in the polynomial. So, maybe that's how you found that value.
If you switch to bytes mode the site expects a sequence of character code values and ignores whitespace (apart from treating it as a delimiter). You can put 0x54 0x45 0x4d 0x50 0x53 into it in bytes mode to see 0x49 result also. You can then add 0x0D (newline) to see it to result in a 0x6E from before.
Regarding the middle site, the settings aren't correct (the reverse setting is on for input and output) and I don't see how to make them correct; they don't seem to have a custom option. However, you can turn on the reflect options on the first site to get the same result as in the 2nd site in order to convince yourself that is what is going on. The third site's output is correct for what you've put into it. It just doesn't match what you're code is actually doing.
Your basic problem is the +1 in this line:
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);

You've included the null terminator in the calculation. This is 7 bytes: 'T', 'E', 'M', 'P', 'S', ';', '\0'. These websites just aren't doing that; they are not automatically adding a null terminator at the end of whatever you type in string mode. Alternately, if you wanted the null terminator in the CRC calculation, your code is fine, but you're going to need to switch to HEX input mode on the website and enter a 0x00 into it after the hex values for the other characters in TEMPS; so as to match. And it will match, I've tested this. You can also: put the first site into bytes mode and put "0x54 0x45 0x4d 0x50 0x53 0x3b 0x00" into it and you will see it now produces a 0xB5, like your current code.
Otherwise, you just need to not enter the null terminator into the calculation:
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);

This will result in 0x49 coming out of crcTrame.getCRC() instead of 0xB5:
#include "CRC8.h"

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

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();
  char arrayForCrc[crcDataLength+1];
  crcData.toCharArray(arrayForCrc, crcDataLength+1);

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}

If you also want to sanity check what happened with the 0x6E output earlier, you can then change crcData to String crcData = "TEMPS;\n" (adding the newline) and watch it start printing 6E.

There's a .getBytes() function in String that is pretty much what you have without needin the cast:
crcTrame.getBytes(arrayForCrc, crcDataLength);

I'm not sure if you have a good reason for "TEMPS;" to begin life in a String or then to have to get it into an character array. If you're only doing this so you can then call crcTrame.add(), well, you needn't:
#include "CRC8.h"

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

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add(
    (const uint8_t *)crcData.c_str(),
    crcData.length() // <- Does not count null terminator.
  );
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}

Note: I'm only creating stringCrc to mirror what you were doing. Here, it could just as easily be Serial.println(crcTrame.getCRC(), HEX); and potentially in whatever context you're doing it in. The cast can also be done in a more C++ approved (though uglier way with crcTrame.add(reinterpret_cast<const uint8_t *>(crcData.c_str()), crcData.length());
Any sequence of any number of add() calls that delivers the same data in the same order into calculation will yield the same CRC. There's also an overload of add() that takes an individual character without needing to involve a pointer at all. So your data doesn't need to come from a String, nor be a null-terminated string, or character array, nor fit entirely in memory.


text:
Writing Arduino code for MPXV6115V pressure sensor
I'm attempting to use an MPXV6115V pressure sensor to monitor the constant vacuum of a suction device. I haven't been able to find a library to use with this sensor. I'm very new to Arduino but I am a software developer so would like to write some code to get this sensor working. The datasheet for this sensor can be found here. I've had some success using the code found here but this is for a different MPX pressure sensor and the output doesn't look right, I believe my constant values might need adjusting but not sure.
I've heard I may be able to use the transfer function for the basis of the code? I'm really not sure where to start with that. Could someone please explain how I can write the code to get this sensor working with the Arduino? Thank you.

why would you need a library? ... the sensor outputs voltage that is proportionsl to the pressure ... measure the voltage

The linked code basically just does analogRead()s, calculates a real world value from the results and sends it over Serial. Thats also what you want to do, you just need to change the calculation.
So take the transfer function of your sensor and reorder it so that you get a formula for P:
P = (Vout/Vs - 0.92)/0.007652

with Vs being the supply voltage (5V in this case) and Vout being the output voltage. The ADC of the Arduino is 10 bits, so it gives you a value in the range of 0 to 1023 for 0V to 5V. So you get the voltage by calculating
voltage = analogRead(pin) / 1023.0 * 5.0;

Now put that into the formula above, write it as proper C++ code (for the variables use float as type, while pin is an integer and is the pin you connected the sensor to, like A0) and then replace the calculation in the linked code with yours - or wrote your own complete code. There isn't much to do besides analogRead(), the calculation and corresponding Serial.println() calls.


text:
Convert uint8_t array to uint32_t array
I have this array of bytes, that I need to convert to an array of unsigned ints. Also the function (btea) that needs it, seems to need a pointer.
I'm currently using reinterpret_cast which seems to work, but I'd like to know how/why. I'm pretty new to C. It also seems kind of dirty. I could use a for loop, and bitshift everything into a separate int array variable, but that seems wasteful.
uint8_t data[] = {1,2,3,4,5,6,7,8};//can be any multiple of 4 bytes

btea(reinterpret_cast<uint32_t*>(data), sizeof(data)/4, encryption_key);

radio.write(data, sizeof(data));

...

void btea(uint32_t *v, int n)
{
  ...
}

Any pointers (pun intended) are much appreciated.

@mpflaga's answer gives a great alternative, but I thought I'd explain why your code works (grossly simplified).
All the reinterpret cast does is let the compiler know how wide of a variable it assumes is in each element of the array.  When you access data[1], it uses one byte at an offset of one byte from data[0].  When you cast to uint32_t and access data[1], it uses 4 bytes at an offset of 4 bytes.
If your memory looks like this (each square is one byte)...

...before the cast you are interpreting it as the top layout, after the cast you interpret it as the bottom layout.  It's still exactly the same in memory, you're just telling the compiler to use it differently. The reason that using a union is better is that it is safer.  Your code would read garbage after the end of the array if its length wasn't divisible by 4.
One other quick note, be careful with the sizeof() operator on arrays - it always gives the length in bytes regardless of the element size.

about the sizeof() I usually employ "#define LENGTH_OF_ARRAY(x) ((sizeof(x)/sizeof(x[0])))". Noting it is the size of the whole array divided by the size of an individual element.

Great explanation. But what about the * in reinterpret_cast<uint32_t*>. Why doesn't it reinterpret the array-data as a pointer?

@Gerben - That's because they both refer to the same memory location.  data[0] and *data are both the equivalent, but use different semantics. In fact, data[1] and *data + 1 are also equivalent.  The main difference to keep in mind is that when you declare and array like uint8_t data[7]; the compiler reserves 8 contiguous bytes of RAM and a memory address, but when if you declare uint8_t* data, it only gets you an address. There's a decent tutorial here that gives more justice to the concept than I can in a comment.

I prefer to use unions. example:
union fourbyte {
  uint32_t dword;
  uint16_t word[2];
  uint8_t  byte[4];
};

union fourbyte val;

val.dword = 0x03020100;

Serial.println(val.byte[0], HEX);
Serial.println(val.byte[1], HEX);
Serial.println(val.byte[2], HEX);
Serial.println(val.byte[3], HEX);

Serial.println(val.word[0], HEX);
Serial.println(val.word[1], HEX);

Serial.println(val.dword, HEX);

My byte array is of length 8. So I could do something like union eightbyte {uint32_t dword[2];  uint16_t word[4];  uint8_t  byte[8];};. Variable length arrays seem be impossible using this method.

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


text:
Using Random() and Greater Than
Total Arduino noob, I come from a Python "background", though I barely know that, either.
I'm writing a super simple script that will turn on a bulb when the random number generator generates a number greater than 100. Obviously, I have a syntax problem or something: What am I doing wrong? Secondly, How quickly does random query numbers? Is it possible to slow it down? I don't need my bulb turning on 50 times a second.
Thanks! And please be kind; I know this is Googleable, I just lack the prerequisite knowledge to Google this efficiently.
/*

*/
int relayPin = 7;
int randomNumber = random(1001);

void setup() {
  pinMode(relayPin, OUTPUT);

}

void loop() {

if(randomNumber > 100)
  digitalWrite(relayPin, LOW);

else{
   digitalWrite(relayPin, HIGH);}

}```

what is the problem?

btw, put the ``` on a separate line so that it is invisible

The problem is that the relay module does not switch. I assume that there is an error in my code.

yes, logic error ... ask yourself  when is the value of randomNumber updated?

The current code (if you move the random number generation into loop()) will switch not just 50 times, but thousands of times per second. Look at some example code to get an idea about how to solve that.

Start to learn, aka "build knowledge", by looking into some of the provided examples... ;-)

Start with the blink example and think how you can randomise it...

There are a few things to be discussed in here.
First, the random number generation: in fact, the arduino does not generate random numbers. It has a list of numbers on its memory that just "seems" to be random. That's why it's called a pseudo-random number.
So, you need to declare a starting point on this sequence, from which you will get the "random" numbers. This is made with "randomSeed()" in void setup. For example:
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point,
                             //in this case, the analogRead value of an unconnected pin
}

Next, let's generate our number. The variable can be global (as you declared it outside any function), but you must declare it with "random()" only inside "void loop". Otherwise, its value will be assigned just one time (that's what your code is telling it, to do it once).
Here is what I would do:
int relayPin = 7;
long randomNumber; //just declares the variable; it must be type "long"

void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  pinMode(relayPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  randomNumber = random(0, 301);
  //each time the code loops, it assings another value to randomNumber
  //in this case, the number will be between 0 and 300 (301 is the excluded limit)

  if(randomNumber > 100){
    digitalWrite(relayPin, HIGH);
  }
  else{
    digitalWrite(relayPin, LOW);
  }
  delay(500); //half a second delay

}

If you want to have more details about how random numbers are generated in the Arduino, visit the Arduino language Reference:
https://www.arduino.cc/reference/en/

Thank you for this! This explanation was very kind and helpful of you! I will implement this after work.


text:
1 global variable consuming 19% of memory
I am working on a simple project on talking to the serial monitor, and my only global variable ("int" type, named "incomingByte") is consuming a lot of memory. There is no problem on running the scketch, but I am not satisfied to have it that way.
When I load it, I receive: "Global variables use 390 bytes (19%) of dinamic memory...".
Why is it happening, and how could I fix this?
int incomingByte = 0; //for the incoming serial data
void setup() {
  // put your setup code here, to run once:
  randomSeed(analogRead(0)); //starts the pseudo-random sequence in a random point
  Serial.begin(9600);
  //waits for serial initialization to send the messages:
  //(Serial) returns false for serial off, and true for serial on. This is inverted with !.
  while(!Serial){
    ;
  }
  //sending instructions:
  Serial.println("Initializing...");
  Serial.println(" ");
  delay(2000);
  Serial.println("Please select an option:");
  Serial.println("1 - greetings");
  Serial.println("2 - random number");
  Serial.println("3 - calculator");
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial.available() > 0){
    incomingByte = Serial.read(); // Serial.read() returns the first byte of incoming data

    //recognizing the command received:
    if (incomingByte == '1'){
      numberOne();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '2'){
      numberTwo();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
    if (incomingByte == '3'){
      numberThree();
      delay(1500);
      Serial.println("Waiting; choose another option");
      Serial.println(" ");
    }
  }
}

void numberOne() {
  Serial.println("Hello, Vitor! Good to see you!");
}

void numberTwo() {
  //sets the random number to be picked between [0, 101[
  long randomNum = random(0, 101);
  Serial.print("Your random number is: ");
  Serial.println(randomNum, DEC);
}

void numberThree(){
  Serial.println("Tool not available yet");
}

Why do you think, that all the dynamic memory allocation is for that variable? Other things (like Serial) also use some of the RAM

I think that because the message I receive is telling "Global variables". As you said, does the object "Serial" count as a global variable, when using RAM?

Yes, it is global. It's just defined in a different file (inside the used Arduino core), but there at global scope

The random seed also needs to be stored somewhere, or some other state for the RNG.

Just out of curiosity, if you have two global variables, do they use 38% of memory?

A few things that count towards the “global variables” that you may not
think of:

all your literal strings, unless encapsulated within the F()
macro; you have quite a few of them
The Serial object, including its transmit and receive buffers (157
bytes on an Uno)
The vtable for HardwareSerial (that's the class Serial belongs
to, 18 bytes)
The time-keeping variables (9 bytes).

And then, on top of that, there are the actual global variables of your
code, and the static locals which, for the purpose of memory allocation,
are the same as globals. An int, for example, takes 2 bytes on
AVR and 4 bytes on most other hardware platforms.

Edit: answering the questions in a comment

every single time I call Serial it will increase the memory
consumption of the code?

I don't quite understand what you mean by “every time”:

Every time you add a reference to Serial to a sketch, the linker
will add the Serial object to your compiled code, and the program's
RAM consumption will grow by the size of this object.
Within a single sketch, whether Serial is used once or many times
makes no difference: the object will be instantiated only once.

why does the IDE considers everything that uses RAM as a global
variable?

When it says “global variables” it actually means “statically allocated
data”. It says “global variables” because it is targeted at beginners,
and the authors assume beginners would not understand what static
allocation means. Globals are the simplest form of static allocation.

is there a difference in consumption between globals and locals?

Yes. Globals get allocated statically, i.e. at compile time. That's why
the IDE can report how much space they will consume. Locals (at least
non-static locals) get allocated and deallocated on the stack, at run
time. Short of running the program in an emulator, it is very hard to
predict how much stack space a program will consume, as this will
usually depend on run-time events.

I understood about the literal strings and the serial consumption, but I couldn't get some points. Firstly, every single time I call Serial it will increase the memory consumption of the code? Also, why does the IDE considers everything that uses RAM as a global variable? (is there a difference in consumption between globals and locals?)

@VitorZ.: se expanded answer.

Oh now I got it! Your explanation was very useful and complete, thank you. By using your tip in transferring the strings to PROGMEM with F(), I could reduce the SRAM consumption from 19% to only 9%, with just 1% more of Flash usage.


text:
I can't get my Micro Pro to bootloader mode anymore
It's important to start by saying that this micro was working perfectly, and the keyboard I built with it was great. Then this happened:
While using the QMK Toolbox I tried to upload an oversized .hex file, and since it was taking too long, I hit the reset button. Clearly uploading an oversized hex file was the problem here.
Now the pro micro won't respond to anything. The green LDE lights up, but windows won't recognize it. I tried clicking the reset button and grounding the reset pin, and nothing works. I even tried the double tap on the reset key, or the tap and hold, nothing.
Have I totally broken the micro somehow? Can't I hard-reset it?

Reinstall the bootloader...

how @Majenko? I can't connect to it....

did you try a double reset? it activates the bootloader

@Juraj, " even tried the double tap on the reset key,"

@Deleteman With another Arduino or hardware programmer (USBASP for example).

Can I use another pro micro for this?  @Majenko

Yes, you sure can.

Alright, just answering my own question in case someone comes along in the future:
The problem in my case, as @Majenko mentions in the comments, was the bootloader. In my case, there was no way around it, I had to re upload it with a ISP.
I got another Arduino Pro Micro and using the wiring from this answer: Trying to verify that Arduino Pro Micro ISP is working and following this tutorial: https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP
I managed to get it working.
Notes:

I did not have to change anything on the code for the ISP sketch.
Careful with the picture from the first answer, the comments show an issue with the wiring you need to take into account.

After that, the "Burn bootloader" action worked like a charm.


text:
How to make an Arduino act reliably as an SPI slave?
I want two Arduino Nanos to communicate with each other using SPI, ideally at around 2MHz or faster.
I have two standard Nanos running at 16MHz on 5V.

The master uses SPI.transfer() to send an array across the wire.¹ For ease of troubleshooting, the array alternately contains a bunch of zeroes or a bunch of 255s; but never both.

The slave simply returns decimal 66 for every byte. This was chosen because it's easy to spot on a logic trace.

The master checks the responses, and if there are any values that aren't 66, it prints the array to the UART.

Even at 125Kbit, which is the slowest available speed, I'm regularly getting corrupted bytes. Interestingly, most of the time (but not always!) the corrupted byte is either 0 or 255 - in other words, exactly the same as the byte sent from the master! This strikes me as a very unlikely coincidence.
I have inspected the traffic with a logic analyser, and it seems that the slave just occasionally decides not to operate as instructed; and instead it just sends the input straight out again. As in, the byte going out on MISO is exactly the same as the byte coming in on MOSI. But only sometimes.
What is happening here? Why doesn't it work? And what can I do about it?

Master sketch:
#define MOSI    12
#define SCK     13

#include <SPI.h>
#include "pins_arduino.h"
#include <avr/wdt.h>

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

    digitalWrite(SS, HIGH);
    pinMode(SS, OUTPUT);
    digitalWrite(SCK, HIGH);
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);

    SPI.setClockDivider(SPI_CLOCK_DIV128);      // 125KHz
    SPI.begin();

    Serial.println("\n\nSTARTING...\n");
}

void do_transfer(byte attempt, byte payload) {

    // packet size of 200
    byte buffer[200];

    // initialise packet
    for (byte count = 0; count < sizeof(buffer); count++)
        buffer[count] = payload;

    // perform transfer
    digitalWrite(SS, LOW);
    SPI.transfer(buffer, sizeof(buffer));
    digitalWrite(SS, HIGH);    // SS is pin 10

    // tally results
    byte successes = 0, failures = 0;
    for (byte index = 0; index < sizeof(buffer); index++)
        if (buffer[index] == 66) successes++; else failures++;

    // print results
    Serial.print("Attempt ");
    Serial.print(attempt);
    Serial.print(" with payload ");
    Serial.print(payload);
    Serial.print(": ");
    if (failures == 0)
        Serial.print("SUCCESS");
    else {
        Serial.print(successes);
        Serial.print(" correct bytes, ");
        Serial.print(failures);
        Serial.print(" incorrect bytes");
        for (byte index = 0; index < sizeof(buffer); index++) {
            if (index % 10 == 0)
                Serial.print("\n\t");
            if (buffer[index] == 66)
                Serial.print("-");
            else
                Serial.print(buffer[index]);
            if (index < sizeof(buffer) - 1)
                Serial.print("\t");
        }
    }
    Serial.println();
    Serial.println();
}

void loop(void) {
    delay(800);                                                         // give the slave time to be ready

    for (byte attempt = 1; attempt <= 10; attempt+=2) {
        do_transfer(attempt, 0x00);
        do_transfer(attempt+1, 0xFF);
        wdt_reset();
    }
    while(true);                                                        // end of program
}

Slave sketch:
#include "pins_arduino.h"

void setup(void) {
    pinMode(MISO, OUTPUT);          // MISO needs to be an output
    SPCR |= _BV(SPE);               // enable SPI in slave mode
    SPCR |= _BV(SPIE);              // enable interrupts
    SPDR = 66;
}

ISR (SPI_STC_vect) { SPDR = 66; }   // just send 66 until the cows come home

void loop (void) { }

Connections: The following pins on both Arduinos are connected together:

SS (pin 10)
MISO (pin 11)
MOSI (pin 12)
SCK (pin 13)
GND

¹ The problem also happens if I send one byte at a time using SPI.transfer(), unless (maybe) if I insert a 1ms delay between each byte. Which of course is ridiculous.

What happens with smaller delays between the bytes (like microsecond range)? For me it sounds like in the error cases a new byte gets clocked by the master before the ISR can run on the slave (which replaces the last received byte with the new answer byte). This can happen, when another ISR is currently running. You could also try to disable the Timer0 interrupts in the slave sketch, since Timer0 is used for time keeping in the Arduino core. Functions like millis(), micros() and delay() won't work anymore then.

@chrisl your suggestion of disabling the timer worked. Mostly. But while it now works up to 250KHz, I get many many errors at 500KHz. Many of the MISO bytes are delayed by one bit.

I'm getting erroneous '33' bytes returned when I send the zeroes, and I'm getting erroneous '161' and '194' bytes returned when I send 255s. This seems very specific. Any ideas?

Honestly I doubt that you will get much faster. The bottleneck is clearly that you cannot write the buffer fast enough. The Nano is just too slow. Others on this site can surely give you a good estimate of the needed time for the interrupt by counting the needed cycles.

About the specific error values: I'm currently not sure if the SPI data register is a buffered one. If not it is pssible that your code writes that register and in the middle of that the SPI hardware already sends the half written data out. Not sure about that

The datasheet says "when the SPI is configured as Slave, the SPI is only guaranteed to work at fosc/4 or lower." So I don't think that's the issue. Also, according to the datasheet, the SPI register is "double buffered in the receive direction".

Your problem here is timing. I tried your setup, and found that I did indeed get occasional errors at 125 kHz. Disabling Timer 0 (as suggested by Chrisl) fixed that:
  power_timer0_disable();

But while it now works up to 250KHz, I get many many errors at 500KHz.

OK, the time between clock pulses is now 2 µs, however as I document here the time taken to execute an ISR like SPI_STC_vect is 2.625 µs, therefore it can't keep up with having to put the data there every 2 s.
You actually have slightly more time than 2 µs because the critical time is the time between the end of the first byte (which is when the ISR is called) and the time before the start of the second byte, which is when the master will start sampling your response.
See screenshot below with the critical time boxed in yellow.

That time is 2.45 µs and the ISR takes 2.625 µs. Now some of that is the ISR epilogue which won't really matter that much, but you can see that things are tight. It's hard to know exactly at what point the processor starts calling the ISR after the last bit arrives, and the length of the instruction it is currently executing could be an influencing factor.
I got your sketches to work running at 250 kHz with these amendments to the slave:
#include "pins_arduino.h"
#include <avr/power.h>
#include <avr/sleep.h>

void setup(void) {
  pinMode(MISO, OUTPUT);          // MISO needs to be an output
  SPCR |= _BV(SPE);               // enable SPI in slave mode
  SPCR |= _BV(SPIE);              // enable interrupts
  SPDR = 66;
  power_timer0_disable();
  set_sleep_mode (SLEEP_MODE_IDLE);
}

ISR (SPI_STC_vect) { SPDR = 66; }   // just send 66 until the cows come home

void loop (void)
 {
 sleep_mode ();
 }

The sleeping in idle mode makes sure that the processor is not half-way through an instruction when the interrupt is raised.
As expected (for the reasons above) it did not work at 500 kHz.
If you want to transfer data reliably you need to allow, in the master, for the time it takes the slave to do stuff. Every line of code in the slave means that the master has to wait for that to be executed.
I mention that in my page about SPI where I build in a delay in the master, if I want the slave to do calculations or something.

But the datasheet says that speeds of Fosc/4 are possible in slave mode, which would be 4MHz in this case. Would that be achievable if I removed the ISR and just used a busy loop?

Well, yes the datasheet has an example of doing a busy loop:
char SPI_SlaveReceive(void)
{
/* Wait for reception complete */
while(!(SPSR & (1<<SPIF)))
;
/* Return Data Register */
return SPDR;
}

Regardless of what they claim, what you intend has to be physically possible. So with Fosc/4, assuming a 16 MHz clock, you have 2 µs for a byte to arrive (250 ns * 8). So the hardware may well be able to receive one byte in that time, and you may just have enough clock cycles to notice it arriving and plonk it into memory somewhere (although things could be tight) but you won't have time to send a different response after each incoming byte, because you only have around 250 ns to do it in, and the loop that detects the interrupt will probably use up most or all of that.
After a bit of mucking around, I got it to work at 250 kHz where the objective was just for the slave to return some data (after all, I presume that is what the slave is supposed to do).
Master
#define MOSI    12
#define SCK     13

#include <SPI.h>
#include "pins_arduino.h"
#include <avr/wdt.h>

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

    digitalWrite(SS, HIGH);
    pinMode(SS, OUTPUT);
    digitalWrite(SS, HIGH);

    digitalWrite(SCK, HIGH);
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);

    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV64);

    Serial.println("\n\nSTARTING...\n");

}

void do_transfer(byte attempt, byte payload) {

    // packet size of 200
    byte buffer[200];

    // perform transfer
    digitalWrite(SS, LOW);
    delay (1);    // give slave time to react
    SPI.transfer(buffer, sizeof(buffer));
    digitalWrite(SS, HIGH);    // SS is pin 10

    // tally results
    byte successes = 0, failures = 0;
    for (byte index = 0; index < sizeof(buffer); index++)
        if (buffer[index] == index) successes++; else failures++;

    // print results
    Serial.print("Attempt ");
    Serial.print(attempt);
    Serial.print(" with payload ");
    Serial.print(payload);
    Serial.print(": ");
    if (failures == 0)
        Serial.print("SUCCESS");
    else {
        Serial.print(successes);
        Serial.print(" correct bytes, ");
        Serial.print(failures);
        Serial.print(" incorrect bytes");
        for (byte index = 0; index < sizeof(buffer); index++) {
            if (index % 10 == 0)
                Serial.print("\n\t");
            if (buffer[index] == index)
                Serial.print("-");
            else
                Serial.print(buffer[index]);
            if (index < sizeof(buffer) - 1)
                Serial.print("\t");
        }
    }
    Serial.println();
    Serial.println();
}

void loop(void) {
    delay(800);                                                         // give the slave time to be ready

    for (byte attempt = 1; attempt <= 10; attempt+=2) {
        do_transfer(attempt, 0x00);
        do_transfer(attempt+1, 0xFF);
        wdt_reset();
    }
    while(true);                                                        // end of program
}

Slave
#include "pins_arduino.h"
#include <avr/power.h>
#include <avr/sleep.h>

const int TEST_SIZE = 200;

volatile byte my_data [TEST_SIZE];

volatile byte dummy;

ISR (PCINT0_vect)
 {
 // handle pin change interrupt for D8 to D13 here

  // ignore transition to HIGH
  if (digitalRead (SS) == HIGH)
    return;

  SPDR = 0;

  for (byte i = 0; i < TEST_SIZE; i++)
    {
    SPDR = my_data [i];
    while(!(SPSR & (1<<SPIF)))
      {
      // if SS went high, give up
      if (PINB & (1 << 2))
        return;
      }
    } // end of for loop

 }  // end of PCINT0_vect

void setup(void) {
  pinMode(MISO, OUTPUT);          // MISO needs to be an output
  SPCR |= _BV(SPE);               // enable SPI in slave mode
  power_timer0_disable();
  for (int i = 0; i < TEST_SIZE; i++)
    my_data [i] = i;

  // pin change interrupt for D10
  PCMSK0 |= bit (PCINT2);  // want pin 10
  PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13

  SPDR = 0;

  set_sleep_mode (SLEEP_MODE_IDLE);

}

void loop (void)
  {
  sleep_mode ();
  }

At the next clock divisor (SPI_CLOCK_DIV32) I started getting occasional errors. After all, Fclk/32 is only 2 µs per clock pulse and 16 µs per byte, and the necessary stuff in the inner loop must be taking that long — I didn't calculate the individual instruction times, you are welcome to do that. :)
I was hoping to get better performance than that, but then I realised that even with a tight sending loop in the slave, you can't afford to send before the master has acknowledged the previous byte (ie. that it has read it) so you still have the tight interval between the end of one byte and the start of the next, which is the time in which you have to prepare the next byte for sending.
It's not as bad if you are the master, because you control when the byte starts, so you can take as long as you want between bytes.

I see. But the datasheet says that speeds of Fosc/4 are possible in slave mode, which would be 4MHz in this case. Would that be achievable if I removed the ISR and just used a busy loop?

See expanded reply above.

Yes, this looks like the way to go. I made a few modifications to the code and increased the crystal to 20MHz, and managed to achieve 1.5Mbps - although admittedly without any actual processing taking place, not even storing the value. So probably 1Mbps will be achievable. Thanks for the help!

Honestly, I never thought of putting the busyloop inside an interrupt. It's a great idea.

My conclusion from Nick's excellent explanations, reading the specifications and based on my own experience (a two-slave system is running without problems since more than a year):
The hardware of an Arduino can reliably send and receive a single byte at 4MHz SPI clock, because dedicated hardware is used.
One can expect that SPI.transfer(bytes, size) can reliably send the bytes at full hardware speed, and even receive reliably the same amout of bytes. It is not specified what the maximum speed is in this case, what the maximum size is, and whether other interrupts are disabled. The library may even disable all and use polling to check for the end of a transfer. So a very long transfer may disturb your system upto failure.
Receiving a block of bytes requires that the slave can process the data at SPI byte speed. If hardware shift registers are used (e.g. in an SD card), you may send many bytes reliably at full speed.
But your Arduino slave has a hardware buffer of 8 Bits only, and the time when the interrupt routine is run is NOT when the last bit of a byte has been sent, but some time later. To predict this time reliably is not trivial. Determining it by experiment is not reliable per se.
Thus, when you want to use SPI block transfers, you need to slow down the SPI speed drastically to give the receiver time to process the data during the time of 8 bits.
You may still use full SPI speed, if you send single bytes (without returning SS) and wait the time required by the slave including any interrupt handling delays.
Or you restrict yourself to single byte transfers at full speed, and use a handshake protocol. This may be quicker than the simple block transfer on the sender's side. Unless you can put operation code and data into 8 bits, you have to maintain state information on both sides.
Conclusion: You may receive single bytes at full SPI speed. The function SPI.transfer(block, bytes) sends more than byte, but does not imply that any SPI slave can collect them. In particular, this function is not appropriate for sending data to an Arduino slave.


text:
Cubecell AB01 with nRF24L01
I have been trying to connect a nRF24L01 to a Cubecell AB01 without much luck. Most of the time, the radio.available() function always returns true resulting in a bunch of garbage. I have figured out that the nRF24L01 doesn't want to configure properly. With printPrettyDetails() I can confirm that the settings are not stored.
However, with the example sketch contained within the RF24 library, everything works fine (confirming that the AB01 and nRF24L01 are working fine). But as soon as I change the datatype of the receiver payload to uint8_t, the radio.available() is always true, resulting in a bunch of received messages with garbage. PrintPrettyDetails() also shows the wrong settings.
Does anyone have experience with this? I have also tried the example sketch from Robin2. This results in a lot of garbage as described before.
I am using:

nRF24L01 with pcb antenna. I am periodicially using an esp32 to test that the nRF24L01 is still functioning okay
a heltec AB01. The nRF24L01 is connected to the spi interface and CE -> GPIO3 and CSN -> GPIO2
To program I'm using platformio. But in desperation I am also able to use the Arduino IDE (exactly the same behaviour)

RX code:
/**
* See documentation at https://nRF24.github.io/RF24
* See License information at root directory of this library
* Author: Brendan Doherty (2bndy5)
*/
    /**
     * A simple example of sending data from 1 nRF24L01 transceiver to another.
     *
     * This example was written to be used on 2 devices acting as "nodes".
     * Use the Serial Monitor to change each node's behavior.
     */
    #include <SPI.h>
    #include "printf.h"
    #include "RF24.h"

    // instantiate an object for the nRF24L01 transceiver
    RF24 radio(GPIO3, GPIO2); // using pin 7 for the CE pin, and pin 8 for the CSN pin

    // Let these addresses be used for the pair
    uint8_t address[][6] = {"1Node", "2Node"};
    // It is very helpful to think of an address as a path instead of as
    // an identifying device destination

    // to use different addresses on a pair of radios, we need a variable to
    // uniquely identify which address this radio will use to transmit
    bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to                                 transmit

    // Used to control whether this node is sending or receiving
    bool role = false;  // true = TX role, false = RX role

    // For this example, we'll be using a payload containing
    // a single float number that will be incremented
    // on every successful transmission
    float payload = 0;

    void setup() {

      Serial.begin(115200);
      while (!Serial) {
        // some boards need to wait to ensure access to serial over USB
      }
      pinMode(Vext, OUTPUT);
      digitalWrite(Vext, LOW);
      delay(10);
      // initialize the transceiver on the SPI bus
      if (!radio.begin()) {
        Serial.println(F("radio hardware is not responding!!"));
        while (1) {} // hold in infinite loop
      }

      // print example's introductory prompt
      Serial.println(F("RF24/examples/GettingStarted"));

      radioNumber = 1;
      Serial.print(F("radioNumber = "));
      Serial.println((int)radioNumber);

      // Set the PA Level low to try preventing power supply related problems
      // because these examples are likely run with nodes in close proximity to
      // each other.
      radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX is default.

      // save on transmission time by setting the radio to only transmit the
      // number of bytes we need to transmit a float
      radio.setPayloadSize(sizeof(float)); // float datatype occupies 4 bytes

      // set the TX address of the RX node into the TX pipe
      radio.openWritingPipe(address[radioNumber]);     // always uses pipe 0

      // set the RX address of the TX node into a RX pipe
      radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1

      // additional setup specific to the node's role
      if (role) {
        radio.stopListening();  // put radio in TX mode
      } else {
        radio.startListening(); // put radio in RX mode
      }

      // For debugging info
      // printf_begin();             // needed only once for printing details
      // radio.printDetails();       // (smaller) function that prints raw register values
       radio.printPrettyDetails(); // (larger) function that prints human readable data

    } // setup

    void loop() {

        // This device is a RX node

        uint8_t pipe;
        if (radio.available(&pipe)) {             // is there a payload? get the pipe         number that recieved it
          uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
          radio.read(&payload, bytes);            // fetch payload from FIFO
          Serial.print(F("Received "));
          Serial.print(bytes);                    // print the size of the payload
          Serial.print(F(" bytes on pipe "));
          Serial.print(pipe);                     // print the pipe number
          Serial.print(F(": "));
          Serial.println(payload);                // print the payload's value
        }

    } // loop

I have tried anything I could think of, without success. Any help would be appreciated!

Turned out to be a corrupt library and an SPI speed mismatch


text:
external power supply for servo motor attached to redboard arduino
I'm new to this page but I was hoping to get some advice on a servo motor arduino project I'm currently working on.
I have a HS-815BB servo motor (4.8~6V, max stall current draw 6,000mA) and a Spark Fun Redboard. I know I should hook up an external power supply to my servo motor to avoid frying my board. I've seen x4 AAA battery packs that can output 6V, as well as breadboard power supply modules with 3.3V/5V output. However, the breadboard power supply module has a max output current of 700mA and I'm not sure about the battery pack.
Where can I find a power supply that is arduino compatible and outputs ~6V while having a max current draw of 6A or over? Am I looking for the right thing?
Thanks in advance

With 6A you are at a very high current.
First about the batteries: I wouldn't trust in 4 AAA batteries in supporting that high of a current. You may get away with it, if you only have very short bursts of 6A, but I guess the voltage will take a significant dip here. I would look into LiIon or LiPo battery packs, like the ones used for drones (which also can have high current spikes). But please take care to also use a fitting charging circuit. You can find many resources about that on the web.
Now about the breadboard: Just don't pull 6A through a breadboard! Breadboards are not made for currents this high. The contacts have a resistance that is significant in this situation and the metal strips used in there are also not meant for carrying that much. Going over 1A is probably no good for a breadboard. Instead you should connect the power supply outside of the breadboard by soldering or using proper connectors, which can handle the current. You can hook up your breadboard power regulator to the same battery if you want to provide it from the same source.

Where can I find a power supply that is arduino compatible and outputs ~6V while having a max current draw of 6A or over?

There is no "Arduino compatibility" with power supplys. For the Arduino its just about having the correct voltage and being able to provide the needed current to the Arduino (excluding the servo, since it shouldn't be plugged into the breadboard in the first place). When you use a battery and also want to charge it in your circuit, then you need to find a charger board compatible with your chosen battery. Often these boards also have a voltage regulator from which you can get the 5V that you need to power an Arduino. Otherwise you can buy voltage regulator boards, which can take a full range of input voltages and output a regulated voltage of your liking (controlled via a small potentiometer on the board). These can also be used if you want to use a power supply connected to mains (like the often seen 12V power supplies for LED strips).
So called "breadboard power supply modules" are often not more than a board with pins in positions fitting for a breadboard. They are a pure convenience product. You can also solder pin to the cable of power source and put these into the breadboard. Sometimes these boards also have a voltage regulator, which you can also get without the breadboard connector part.


text:
ESP32 HTTP Update and x-MD5 header
https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPUpdate
I found out that this library can read x-MD5 header but looks like it's going through with the update no matter what MD5 I set. I thought it's for verifying the update, I do md5sum of my bin file on the server and then ESP32 checks the hash of downloaded bin to confirm the file wasn't corrupted during download. Am I wrong here? What's the purpose of this x-MD5 header if not for this?
If it has another purpose, how do I make sure that the bin with the update wasn't corrupted during download so I don't brick ESP32?

there is in Update.cpp a condition if(strlen(expected_md5) != 32)


text:
How to read and parse UART data from human presence radar sensor
I'm working on a project, and I purchased a 24 GHz "Human existence/presence" mm Wave sensor from micradar, the R24DVD1. The output of the module is serial data which varies in length and is of the structure shown below;

The Data element of the stream could get as large as 5bytes and as show each package ends with a 0x54 0x43.
My intention is to have my Arduino Uno read the data for further processing. Since I use the Arduino Uno which has only one physical serial port, I felt using it to read the sensor data could prove problematic since the pc is equally connected to that serial line via USB. So I decided to use the SoftwareSerial to read the data from the senor then forward it to the pc and I wrote the following code for that;
#include <SoftwareSerial.h>

const int txpin = 3;
int const rxpin = 2;
SoftwareSerial mySerial(rxpin,txpin);

const unsigned int PACK_SIZE = 14;
int inByte1;
int inByte2;
unsigned int recvdByte = 0;

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

void loop() {
// put your main code here, to run repeatedly:
if (mySerial.available() > 0){
int pack[PACK_SIZE];

inByte1 = mySerial.read();
inByte2 = mySerial.read();

if(inByte1 != 84 && inByte2 != 67){
  pack[recvdByte] = inByte1;
  pack[recvdByte+1] = inByte2;
  recvdByte += 2;
 }
else{
  pack[recvdByte] = inByte1;
  pack[recvdByte+1] = inByte2;
  recvdByte = 0;
 }
for(int i = 0; i < PACK_SIZE; i++)
{
  Serial.print(pack[i],HEX);
}
Serial.println();

 }
}

I would like to know if my thought process in reading and parsing the data is correct because the output is quite inconsistent to what I expect

you read two bytes if maybe only one is available

My thought process was to read two bytes so I can compare if two consecutive bytes are 0x54 and 0x43 then I know it's the end of a frame of data. Any suggestion on how to go about it?@Juraj

First of all, I would advise you against using SoftwareSerial,
especially at this high baud rates: it is a recipe for problems. Since
you seem to be using the link to the computer only for writing, and the
link to the sensor only for reading, you can use the hardware serial
port for both. Connect the sensor's TX to the Arduino RX, and you will
be able to read the sensor data with Serial.read(). Do not connect
the sensor's RX, and you will be able to Serial.print() to the serial
monitor without disturbing the sensor.
Next, you must be aware that serial data is received one byte at a time.
If you waited until you had a full packet in the serial buffer, then
you could read and process the whole packet at once. This is, however,
difficult, because you cannot know the length of the packet before
starting to read it.
I would recommend that instead you process one incoming byte at a time,
and you do the necessary sanity checks in the process. Here is how I
would do it (warning: untested code):
const unsigned int MAX_PACKET_SIZE = 14;
const unsigned char char start_signature[] = {0x53, 0x59};
const unsigned char char end_signature[] = {0x54, 0x43};

unsigned char packet[MAX_PACKET_SIZE];
int recvdByte = 0;  // number of bytes received and buffered so far
int dataLength = 0;  // length of the data field

void processPacket();  // defined elsewhere

// Handle a single input byte.
void processInputByte(unsigned char inByte) {
    if (recvdByte < 2) {  // check the start signature
        if (inByte != start_signature[recvdByte]) {  // wrong signature?
            recvdByte = 0;  // discard the packet
            return;
        }
    } else if (recvdByte == 4) {  // grab the data length
        dataLength = inByte;
        if (dataLength > MAX_PACKET_SIZE - 9) {  // overlong packet?
            recvdByte = 0;  // discard the packet
            dataLength = 0;
            return;
        }
    } else if (recvdByte == 5) {  // check the second data length
        if (dataLength != inByte) {  // doesn't match?
            recvdByte = 0;  // discard the packet
            dataLength = 0;
            return;
        }
    } else if (recvdByte == 6 + dataLength) {  // check sum
        // TODO: Look at the datasheet to see how to control that
        // the checksum is correct. Discard the packet if it is not.
    } else if (recvdByte >= 7 + dataLength) {  // check end signature
        if (inByte != end_signature[recvdByte - (7 + dataLength)]) {
            recvdByte = 0;  // discard the packet
            dataLength = 0;
            return;
        }
    }

    // All correct so far, we can buffer the incoming byte.
    packet[recvdByte++] = inByte;

    // If we have a complete packet now, handle it.
    if (recvdByte == 9 + dataLength) {
        processPacket();
        recvdByte = 0;  // reset for the next packet
        dataLength = 0;
    }
}

You may want to sprinkle a few Serial.println() here and there for
testing and debugging. These could be removed once everything works as
expected.
Then, in the main loop, you just have to:
void loop() {
    if (Serial.available() > 0) {
        processInputByte(Serial.read());
    }
}

Thanks a million Edgar. This with a little modification does the trick most of the time. I will keep working on it to see if I can get it working better


text:
ELEGOO Mega 2560 USB and Vin simultaneously?
I'm powering my Arduino clone with an LM317 circuit that regulates Vin voltage to 10V (measured with a multimeter).  While the Arduino is powered by USB only, everything works.  When it's powered using Vin, I get odd behavior.  I then tried plugging in the USB to see what was happening via the serial monitor and my laptop shut down.  I read the Arduino is supposed to handle both USB and Vin simultaneously without shorting out, but now I'm scared to try it again.  Is it safe to try again?  Any idea what would cause my laptop to shut down, or what I could be doing wrong?  Thanks.

When it's powered using Vin, I get odd behavior ... what is the voltage at Vin when everything is powered on? .... odd behavior doesn't really mean anything ... what actually happens?

Is it safe to try again? ... do not believe anyone that says yes without examining your arduino in person

It should be fine if you don't have Vin less than 6V6. There is a circut that compares half of Vin against 3V3 "reference" and if it's less, then it enables "ideal diode" switch from Vusb (but it also allows backfeeding)
Another way how to bakcfeed usb from the Arduinos 5V is short 3V3 to 5V and having 9V on Vin (eg. less than 10V).
However backfeeding USB port shouldn't be causing restarts. Maybe there are a power supply issues and you've got a big voltage potential difference before connecting it into the USB? You can try to measure it


text:
How do I use BLE module and RFM69 module together?
I am trying to use an Adafruit BLE module and an RFM69 module on the same Arduino.
The higher-level functions in each included library (Adafruit_BLE.h, RFM69.h) both use the SPI.h library to talk to each respective module.
I think all I need to do is make a copy of the SPI.h file, and edit it to make the SS pin for one of the modules different.
Is there a better way to do this?

The SS pin will be defined by the target device library, not SPI.h. Check the options for the constructor in each library for how to change the SS pin from your own code.

you mean like Arduino.h?

No, I mean like RFM69.h or Adafruit_BLE.h or whatever the libraries are called that you are using.


text:
How does C2 work on the ATMega328P?
What is the purpose of C2 on this schematic below?
How does it work when the microcontroller is being programmed?

what happens to DTR when the microcontroller is being programmed?

If SJ1 is connected, and when DTR go from HIGH to LOW, what do you think will happen on the RESET pin?  Also read this.


text:
Standalone ATMega328 - do I need to burn the bootloader?
I want to get an ATMega328 off of the Digi-Key, and use it like an Arduino (without requiring the whole Arduino board).
When it comes to programming, do I need to do anything special like burn the bootloader onto it or something like that?
I want to use the Arduino IDE to program it.

The processor for a home made Arduino is an ATMEGA328P. Note the P at the end or you may encounter invalid signature errors when programming it. There is an unfortunate terminology problem with "burn bootloader" in the Arduino IDE. You need to use "burn bootloader" to set the processor fuses even if you don't want a bootloader. Finally, check the stock level of the ATmega328P at Digikey in advance to avoid disappointment.

At the risk of having my answer closed as "link only" I want to tell you that I have a page describing how to make an Atmega328P into an Arduino-compatible board.
There is far too much detail to post here, but once you have installed your processor with a resistor and a couple of decoupling capacitors you can use another Arduino to burn the bootloader.

Once you have done that you can use an FTDI cable to program your new Arduino-compatible from the Arduino IDE. The cable would be hooked up like this:

Now you can program the chip just using the IDE as if it was a "real" Arduino.

No, you do NOT need to burn the bootloader. But depending on your equipment and programing habits you may want to.
The bootloader used by Arduino (which is known by the name 'optiboot') is used to allow to program the microcontroller via serial interface. If you want to program your microcontroler this way, then you need the bootloader. Otherwise you will need a programmer for In-System-Programing that uses the SPI interface like Atmel AVRISP MKII, any cheap clone like USBtinyISP or any regular Arduino with ArduinoISP flashed on it.


text:
Arduino Nano Atmega328P not sleeping with either <LowPower> or <avt/sleep.h>
I'm working on a battery powered Arduino Nano project. I really need it to save power for hours on end, so I turned to Arduino LowPower Library and avr/sleep.h to do the job.
However, whatever I do, it doesn't look like the board isn't going to sleep. I have a sample sketch that tries to put the board to sleep and then toggles a relay when it wakes up, but it always toggles the relay instantly after booting, so that means it hasn't gone to sleep.
I also measured the current going into the board, and it's drawing 14mA consistently. I would expect to see a much lower draw whilst it's asleep.
Here are the two pieces of code that I've tried, one with LowPower and the other one with avr/sleep.h
void setup(){
    pinMode(relayPin, OUTPUT);
}

void loop(){
    // This call doesn't seem to do anything
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    toggleRelay(); //This gets executed continuously, with no indication of sleep time
}

Here's the other one with LowPower
void setup(){
        pinMode(relayPin, OUTPUT);
    }

    void loop(){
        // This call doesn't seem to do anything
        LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

        //This gets executed continuously, with no indication of sleep time.
        //I would expect it to see it toggle only every 8s
        toggleRelay();
    }

I'm probably doing something stupid, but I can't figure out what... Any help?
Thanks a lot!

I don't know about the LowPower library. However, four your
avr-libc-based test, you forgot to actually put the device in sleep
mode with sleep_mode():
void loop() {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // select a deep sleep mode
    sleep_mode();   // now go to sleep
    toggleRelay();  // executed at wake up
}

Beware that, if you haven't enabled a wakeup source that is active in
the mode you selected, the microcontroller may sleep until it is
power-cycled or receives an external reset.

Oh that was it, yeah! Draw dropped straight down to 5mA. Thanks! I knew it had to be something stupid I'd forgotten.