text:
Problems with Hardware Serial (UART) on Nano 33 BLE Sense
my new Nano 33 BLE Sense arrived today.  I'm working on a project to send data from the the Nano via an Xbee S2C module to a receiver module connected to a Nano 33 IoT.  I had the project working before using an MPU6050 and Mega 2560 board which worked (using Software Serial on the Mega).  On the IoT side, I am using 'Uart XBeeRx  (&sercom0, 5, 6, SERCOM_RX_PAD_1, UART_TX_PAD_0);' to process the data from the Xbee.  Having tried this syntax on the BLE Sense I hit problems and after some Googling found a different syntax.  However my new code isn't working in so far as it compiles, uploads and then crashes the BLE Sense (serial port disappears from tools and the onboard LED blinks slowly and erratically).  I need to keep resetting the board and suspect there is some issue with my hardware serial implementation.  I've cut the code down to simply send accelerometer data.  My code is as follows - the EasyTransfer library simplifies the Xbee comms.  Any help appreciated!
#include <EasyTransfer.h>
#include <Arduino_LSM9DS1.h>

UART XBeeTx (digitalPinToPinName(6), digitalPinToPinName(5), NC, NC);

EasyTransfer ET;

struct SEND_DATA_STRUCTURE {

  float xAcc;
  float yAcc;
  float zAcc;

};

SEND_DATA_STRUCTURE myData;

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {

XBeeTx.begin(9600);

ET.begin(details(myData), &XBeeTx);

}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {

  float x, y, z;

if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);

  }

  myData.xAcc = x;
  myData.yAcc = y;
  myData.zAcc = z;

  ET.sendData();

}

why not use Serial1? (on Mega too)

Hi,  I tried that connecting my Xbee out and in pins to D0 and D1 (UART Rx and Tx) but the same problem and using Serial1.begin(9600) and &Serial1 in the ET.begin statement in the code above.  The Nano Sense seems to lose its USB connection and locks up.  Really can't work out why as it should work.  I think the board is OK as I can run some of the example scripts just fine (e.g. accelerometer and print to the USB serial).  Google seems really light on hits for UART Hardware Serial in the BLE Sense!

The two boards are use different Arduino cores.  The IoT 33 uses a chip family common to Arduino boards; the Nordic Semi ARM chip that's in the BLE Sense is much less so.  The ARM chips used in these devices are only so related.  The  "SERCOM_RX_PAD_1" naming is connected to Atmel (and the 33 IoT); using it as a search term in finding a solution to doing this on your BLE Sense maybe counterproductive.

Doh!  I'm a muppet!!   I'm making a call to IMU without having put IMU.begin() in setup.  I'd deleted it along with some other code that was redundant but added it back in and the project works like a dream!  BLE Sense unit works properly and receiver unit getting the data over the Xbee comms now.  Thanks for the comments though.

@RobM, if this is something that makes sense following from the question, in a way that might be useful to someone else, you can post an answer your own question.  If the solution has nothing to do with the question asked, then probably the thing to do is just delete the question.

You can't make calls to IMU if you haven't initialised it with IMU.begin()

You should be able to mark your own answer as accepted.


text:
Why is our refresh rate consistently decreasing in logging on SD card?
The current code is used to gather the state of 12 infrared beams and log them to an SD card using the real time clock to mark the time. The code uses a switch to turn the device on and off and an LED to indicate if data is being written to the SD. When we later looked at the data on the SD card the refresh rate was slowly decreasing and we ended up with only 10 logs a second after a few hours. Why is this happening and how is it fixed?
#include <SD.h>   //For talking to SD Card
#include <Wire.h>  //For RTC
#include "RTClib.h" //For RTC

//Define pins
//SD card is on standard SPI pins
//RTC is on Standard I2C Pins
const int CS_PIN   = 53;

//Default rate of 25ms
int refresh_rate = 25;

//Define RTC object
RTC_DS1307 RTC;

//Initialize variables
String year, month, day, hour, minute, second, time, date;

#define SENSOR1 22
#define SENSOR2 23
#define SENSOR3 24
#define SENSOR4 25
#define SENSOR5 26
#define SENSOR6 27
#define SENSOR7 32
#define SENSOR8 33
#define SENSOR9 34
#define SENSOR10 35
#define SENSOR11 36
#define SENSOR12 37
#define LEDPIN 6
#define SWITCH 10

// variables will change:
int sensorState1 = 0, lastState1 = 0;
int sensorState2 = 0, lastState2 = 0;
int sensorState3 = 0, lastState3 = 0;
int sensorState4 = 0, lastState4 = 0;
int sensorState5 = 0, lastState5 = 0;
int sensorState6 = 0, lastState6 = 0;
int sensorState7 = 0, lastState7 = 0;
int sensorState8 = 0, lastState8 = 0;
int sensorState9 = 0, lastState9 = 0;
int sensorState10 = 0, lastState10 = 0;
int sensorState11 = 0, lastState11 = 0;
int sensorState12 = 0, lastState12 = 0;

//Variable for reading the Switch Status
int SWITCHSTATE ;

//define integers for sensor change
int SensorChange1 = 0;
int SensorChange2 = 0;
int SensorChange3 = 0;
int SensorChange4 = 0;
int SensorChange5 = 0;
int SensorChange6 = 0;
int SensorChange7 = 0;
int SensorChange8 = 0;
int SensorChange9 = 0;
int SensorChange10 = 0;
int SensorChange11 = 0;
int SensorChange12 = 0;

void setup()
{
  // initialize the sensor pin 24 as an input:
  pinMode(SENSOR1, INPUT);
  digitalWrite(SENSOR1, HIGH); // turn on the pullup  // initialize the sensor pin 25 as an input:
  pinMode(SENSOR2, INPUT);
  digitalWrite(SENSOR2, HIGH); // initialize the sensor pin 26 as an input:
  pinMode(SENSOR3, INPUT);
  digitalWrite(SENSOR3, HIGH); // initialize the sensor pin 27 as an input:
  pinMode(SENSOR4, INPUT);
  digitalWrite(SENSOR4, HIGH); // initialize the sensor pin 28 as an input:
  pinMode(SENSOR5, INPUT);
  digitalWrite(SENSOR5, HIGH); // initialize the sensor pin 29 as an input:
  pinMode(SENSOR6, INPUT);
  digitalWrite(SENSOR6, HIGH);  // initialize the sensor pin 30 as an input:
  pinMode(SENSOR7, INPUT);
  digitalWrite(SENSOR7, HIGH);  // initialize the sensor pin 31 as an input:
  pinMode(SENSOR8, INPUT);
  digitalWrite(SENSOR8, HIGH);  // initialize the sensor pin 32 as an input:
  pinMode(SENSOR9, INPUT);
  digitalWrite(SENSOR9, HIGH);  // initialize the sensor pin 33 as an input:
  pinMode(SENSOR10, INPUT);
  digitalWrite(SENSOR10, HIGH);  // initialize the sensor pin 34 as an input:
  pinMode(SENSOR11, INPUT);
  digitalWrite(SENSOR11, HIGH);  // initialize the sensor pin 35 as an input:
  pinMode(SENSOR12, INPUT);
  digitalWrite(SENSOR12, HIGH);   // initialize the LED pin as an output:

// initialize the LED pin as an output:
  pinMode (LEDPIN, OUTPUT);

// initialize the SWITCH pin as an output:
  pinMode (SWITCH, INPUT);

// setpin 19 as high (5V) and 18 as low
  pinMode(19, OUTPUT);
  pinMode(18, OUTPUT);
  digitalWrite(19, HIGH);
  digitalWrite(18, LOW);

  Serial.begin(9600);
  Serial.println(F("Initializing Card"));

 //CS pin, and pwr/gnd pins are outputs
  pinMode(CS_PIN, OUTPUT);

  //Initiate the I2C bus and the RTC library
  Wire.begin();
  RTC.begin();

  //If RTC is not running, set it to the computer's compile time
  if (! RTC.isrunning())
  {
    Serial.println(F("RTC is NOT running!"));
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }

  //Initialize SD card
  if (!SD.begin(CS_PIN))
  {
    Serial.println(F("Card Failure"));
    return;
  }
  Serial.println(F("Card Ready"));

  //Read the configuration information (speed.txt)
  File commandFile = SD.open("speed.txt");
  if (commandFile)
  {
    Serial.println(F("Reading Command File"));

    while(commandFile.available())
    {
      refresh_rate = commandFile.parseInt();
    }
    Serial.print(F("Refresh Rate = "));
    Serial.print(refresh_rate);
    Serial.println(F("ms"));
    commandFile.close();
  }
  else
  {
    Serial.println(F("Could not read command file."));
    return;
  }

}

void loop()
{
  SWITCHSTATE = digitalRead(SWITCH); //read input value
  if (SWITCHSTATE == LOW)
 {
   digitalWrite(LEDPIN, LOW);
 }
  else
 {
   digitalWrite(LEDPIN, HIGH);

// read the state of the sensor value:
  sensorState1 = digitalRead(SENSOR1);
  sensorState2 = digitalRead(SENSOR2);
  sensorState3 = digitalRead(SENSOR3);
  sensorState4 = digitalRead(SENSOR4);
  sensorState5 = digitalRead(SENSOR5);
  sensorState6 = digitalRead(SENSOR6);
  sensorState7 = digitalRead(SENSOR7);
  sensorState8 = digitalRead(SENSOR8);
  sensorState9 = digitalRead(SENSOR9);
  sensorState10 = digitalRead(SENSOR10);
  sensorState11 = digitalRead(SENSOR11);
  sensorState12 = digitalRead(SENSOR12);

  //Get the current date and time info and store in strings
  DateTime datetime = RTC.now();
  year  = String(datetime.year(),  DEC);
  month = String(datetime.month(), DEC);
  day  = String(datetime.day(), DEC);
  hour  = String(datetime.hour(), DEC);
  minute = String(datetime.minute(), DEC);
  second = String(datetime.second(), DEC);

  //Concatenate the strings into date and time
  date = year + "/" + month + "/" + day;
  time = hour + ":" + minute + ":" + second;

  if (sensorState1 == HIGH)
  {
   SensorChange1 = 1;
  }
  else
  {
   SensorChange1 = 0;
  }
  if (sensorState2 == HIGH)
  {
   SensorChange2 = 1;
  }
  else
  {
   SensorChange2 = 0;
  }
  if (sensorState3 == HIGH)
  {
   SensorChange3 = 1;
  }
  else
  {
   SensorChange3 = 0;
  }
  if (sensorState4 == HIGH)
  {
   SensorChange4 = 1;
  }
  else
  {
   SensorChange4 = 0;
  }
  if (sensorState5 == HIGH)
  {
   SensorChange5 = 1;
  }
  else
  {
   SensorChange5 = 0;
  }
  if (sensorState6 == HIGH)
  {
   SensorChange6 = 1;
  }
  else
  {
   SensorChange6 = 0;
  }
  if (sensorState7 == HIGH)
  {
   SensorChange7 = 1;
  }
  else
  {
   SensorChange7 = 0;
  }
  if (sensorState8 == HIGH)
  {
   SensorChange8 = 1;
  }
  else
  {
   SensorChange8 = 0;
  }
  if (sensorState9 == HIGH)
  {
   SensorChange9 = 1;
  }
  else
  {
   SensorChange9 = 0;
  }
  if (sensorState10 == HIGH)
  {
   SensorChange10 = 1;
  }
  else
  {
   SensorChange10 = 0;
  }
  if (sensorState11 == HIGH)
  {
   SensorChange11 = 1;
  }
  else
  {
   SensorChange11 = 0;
  }
  if (sensorState12 == HIGH)
  {
   SensorChange12 = 1;
  }
  else
  {
   SensorChange12 = 0;
  }

  File dataFile ;
  dataFile = SD.open("log1.csv", FILE_WRITE);
  if (dataFile)
    {
      dataFile.print(date);
      dataFile.print(F(","));
      dataFile.print(time);
      dataFile.print(F(","));
      dataFile.print(SensorChange1);
      dataFile.print(F(","));
      dataFile.print(SensorChange2);
      dataFile.print(F(","));
      dataFile.print(SensorChange3);
      dataFile.print(F(","));
      dataFile.print(SensorChange4);
      dataFile.print(F(","));
      dataFile.print(SensorChange5);
      dataFile.print(F(","));
      dataFile.print(SensorChange6);
      dataFile.print(F(","));
      dataFile.print(SensorChange7);
      dataFile.print(F(","));
      dataFile.print(SensorChange8);
      dataFile.print(F(","));
      dataFile.print(SensorChange9);
      dataFile.print(F(","));
      dataFile.print(SensorChange10);
      dataFile.print(F(","));
      dataFile.print(SensorChange11);
      dataFile.print(F(","));
      dataFile.print(SensorChange12);
      dataFile.println( );
      dataFile.close(); //Data isn't actually written until we close the connection!

      //Print same thing to the screen for debugging
      Serial.println();
      Serial.print(date);
      Serial.print(F(","));
      Serial.print(time);
      Serial.print(F(","));
      Serial.print(SensorChange1);
      Serial.print(F(","));
      Serial.print(SensorChange2);
      Serial.print(F(","));
      Serial.print(SensorChange3);
      Serial.print(F(","));
      Serial.print(SensorChange4);
      Serial.print(F(","));
      Serial.print(SensorChange5);
      Serial.print(F(","));
      Serial.print(SensorChange6);
      Serial.print(F(","));
      Serial.print(SensorChange7);
      Serial.print(F(","));
      Serial.print(SensorChange8);
      Serial.print(F(","));
      Serial.print(SensorChange9);
      Serial.print(F(","));
      Serial.print(SensorChange10);
      Serial.print(F(","));
      Serial.print(SensorChange11);
      Serial.print(F(","));
      Serial.print(SensorChange12);

    }
    else
    {
     Serial.println(F("Couldn't open log file"));
    }

  lastState1 = sensorState1;
  lastState2 = sensorState2;
  lastState3 = sensorState3;
  lastState4 = sensorState4;
  lastState5 = sensorState5;
  lastState6 = sensorState6;
  lastState7 = sensorState7;
  lastState8 = sensorState8;
  lastState9 = sensorState9;
  lastState10 = sensorState10;
  lastState11 = sensorState11;
  lastState12 = sensorState12;

  delay(refresh_rate);
  }

  }

you can streamline your code by using arrays  .... sensorState[1] ,  SensorChange[1] , etc.  ... then use a for loop to iterate over the sensors and update values

This has nothing to do with your question, but that long string of repeated .print()/.println() calls could be moved into a separate function e.g. void printRecord(Print &p) {, which could be called on both dataFile and Serial.  printRecord would contain a sequence (or as jsotola said, array)  of  p.print(....

I couldn't stand looking at the non-loops so I rewrote it as an example for you to look at here. I found a bug when doing so, you update the change variables without looking at the previous value. I didn't compile the code, but it might work anyway!

Why all those "lastState" variables. You don't seem to do anything with them.

I don't have certain answer for you, but a deep suspicion.  If I get bored I'll confirm it. Confirmed below.
In each pass of loop(), you have:
  dataFile = SD.open("log1.csv", FILE_WRITE);

In short, finding the end of the file is linear operation in a FAT filesystem.  It must follow the allocation chain to find (or create), the last cluster of the file.  The allocation chain is sort like a linked list with the links themselves being the only thing in linked list structure; their numbers are mapped onto the cluster numbers.  So you're traversing a linked list, except you may be doing it across multiple sectors of an SD card, which is comparatively expensive.
So by reopening repeatedly in loop(), you're forcing it to perform this lengthening process each time, apparently because of:
dataFile.close(); //Data isn't actually written until we close the connection!

The part of .close(); that does this is made available to you as .flush();, without needing to close the file and forget where the current cluster is.
In other words, you should be able to open() the file once in setup() and replace your .close() in loop() with a .flush().
That said, you needn't and probably shouldn't flush on every record write.  If you're doing this so that you can shut the device down, you might want to just add a push-button that does the closing or flushing and then waits in the tight loop until it's power cycled.
Confirmation Test  Results
In short, yes, there's a measurable, file-size related cost to opening the file for write and seeking to the end. And it's just a fact about the FAT filesystem and noticeable because it's impractical to load the whole allocation table into memory on a small Arduino.  It would normally (e.g on the desktop) be loaded into memory and you'd scarcely notice the difference in opening files of different sizes.
In my one tested scenario for my setup the numbers predict that when the file grows to approximately 155 Meg, it will take about a tenth of a second to open.
This test involved:

An Arduino UNO.
2 GB FAT16 formatted card.
Arduino AVR core version 1.8.3
SD card library version 1.2.4.

Your results will probably vary widely with MCU type and filesystem block size, but so long as you're using a Arduino with a SD library that minimizes memory footprint, you'll have a noticeable increasing open time with larger file sizes.
The below is going to be a bit nerdy, but since people seem to be interested in it, I'm giving some detail.  Arduino code follows at the bottom for what was used to collect the data that produced the graph.
I emptied a 2 GByte SD card.  This included removing the "System Volume Information" that windows (or perhaps the card maker) had put on there, and
confirmed that were were no allocated clusters, no file chains.  Under these conditions the file should just grow in consecutive sectors on the card; at
least as presented by the card, as in: if we ignore anything the card might be doing for wear-leveling.  The pattern used in the program makes it pretty easy
to just look at a raw image of the card and see that this is what happened.
Anyway, with my setup these are some results:

The 98304 sector count on the right refers to a file of roughly 50 Meg.
This SD card is FAT16 formatted, something I hadn't noticed until I ran the numbers on that staircase pattern and found them defying expectations by a factor of 2.
Being FAT16, each FAT table sector, has 512/2 = 256 entries in it.  Each entry number corresponds to one cluster (block), which for my SD card's filesystem happens to be 32 kByte, or 64 count of 512-byte sectors.   So every FAT table sector (in my case) is responsible for locating 64 * 256 = 16,384 file sectors.  In other words, the staircase pattern appears to reflect the fact that following the allocation chain for our consecutive file means reading another FAT table sector for every 16,384 sectors of the file, hence the jumps at those intervals.

If you used a fragmented file it would need to do this more often and the performance would look worse.  I did inspect the SD card to confirm that it was written sequentially.

If you use FAT32, you can expect it to take longer because each FAT sector will store half as many cluster references.

If you use smaller cluster (block) size, then it will take longer because each enter in the FAT sector covers less file content.

Test code
//
// Tested on an UNO with Arduino Core version 1.8.3
// 2 GByte SDCard
//

#include <SD.h> // Version 1.2.4 as of test.
#include <SPI.h>

static constexpr int PIN_SDCARD_SHIELD_CHIP_SELECT = 10;
static constexpr int PIN_HALT_TEST                 =  2;

static const char test_filename[] = "testfile.txt";

struct test_state : Printable {
  uint32_t      sector_counter = -1;
  unsigned long open_duration  =  0;

  size_t printTo(Print& p) const override {
    auto r = p.write('[');
    r     += p.print(sector_counter);
    r     += p.write(':');
    r     += p.print(open_duration);
    r     += p.write(']');
    return r;
  }

  void update(unsigned long new_open_duration) {
    open_duration = new_open_duration;
    ++sector_counter;
  }
};

//
//
//
void write_numbered_sector(
  Print &p,
  const test_state &state
) {
  static constexpr size_t SECTOR_SIZE            = 512;
  static constexpr size_t CR_LF_SIZE             =   2;

  const auto printed_test_state_len = p.print(state);

  const auto xs_to_write =
      SECTOR_SIZE
    - printed_test_state_len
    - CR_LF_SIZE;

  for (size_t i = xs_to_write; i != 0; --i) {
    p.write('X');
  }

  p.write('\r');
  p.write('\n');
}

//
//
//
void setup() {
  pinMode(PIN_HALT_TEST, INPUT_PULLUP);

  Serial.begin(9600);

  if (!SD.begin(PIN_SDCARD_SHIELD_CHIP_SELECT)) {
    Serial.println(F("Card initialization failed."));
    halt_test();
  }

  SD.remove(test_filename);
}

//
//
//
void blink_forever() {
  pinMode(LED_BUILTIN, OUTPUT);
  while (true) {
    static bool led_state = false;

    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    delay(100);
  }
}

//
//
//
void halt_test() {
  SD.end();
  SPI.end();
  Serial.end();

  blink_forever();
}

//
//
//
void loop() {
  static test_state state;

  Serial.flush();
  const auto started_opening = micros();
  File testfile = SD.open(test_filename, FILE_WRITE);
  const auto done_opening = micros();

  const auto open_duration = done_opening - started_opening;

  state.update(open_duration);

  write_numbered_sector(
    testfile,
    state
  );
  testfile.close();
  Serial.print(micros());
  Serial.print(' ');
  Serial.println(state);

  const auto user_requested_halt = (digitalRead(PIN_HALT_TEST) == LOW);
  if (user_requested_halt) {
    Serial.println(F("Test halt requested."));
    halt_test();
  }
}

//  vim:sw=2:ts=2:et:nowrap:ft=cpp:

If you're worried about unattended power loss, you can flush periodically, e.g. every 400 records for a nominal 10s interval - nominal because with a 25ms delay your loop will always take longer than 25ms

Ah yes, the old "doing a resource-intensive operation that should be done only once, but doing it every iteration" problem :)

It is also possible that close instead of flush will cause more writing to the SD card - specifically to the directory sector holding the file entry - causing extra wear (and extra time for the card's controller to load balance sectors (unless flush also touches file entry, if an SD card controller load balances sectors).  Does anyone know?

If I dig through the code again later, I'll check.  My gut reaction is that both will have the same effect on the sectors when called.  But I don't know that.

@mishan it's called a Shlemiel the painter algorithm

Some other useful advice may be found in this answer as well. In particular, using multiple files which can offer some benefits. If I have real cause to edit this again, I'll probably incorporate the link.

source: Stack Exchange

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

sort: votes


text:
if(Serial.available()>0) VS while(Serial.available()>0)
What's the low level difference between if(Serial.available() > 0) and while(Serial.available() > 0)? On what conditions would you choose one over the other?
I was testing my codes on 4 daisy chained 74HC595 shift registers controlling multiple LEDs. The code takes in a number from the serial monitor and displays it out in binary via the LEDs. Here is the code below that worked:
#define latchPin 8  //ST_CP pin of 74HC595
#define clockPin 9  //SH_CP pin of 74HC595
#define dataPin 7   //DS pin of 74HC595

//number of 74HC595 in daisy chain
#define numOfDaisyChainReg 4

byte registerVal[numOfDaisyChainReg];

void setup() {
    Serial.begin(115200);
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
}

void loop() {

  while (Serial.available() > 0) {

    uint32_t num = Serial.parseInt();
    Serial.print(num, DEC);
    Serial.print(" : ");
    Serial.println(num, BIN);

    //breaks the recieved int into 4 unsigned bytes
    //and assigns the byte value into the "registerVal" array
    for (uint8_t a = 0; a < numOfDaisyChainReg; a++) {
      registerVal[a] = (num >> (numOfDaisyChainReg - (a + 1)) * 8) & 0xFF;
      Serial.print("registerVal["); Serial.print(a); Serial.print("] = ");
      Serial.println(registerVal[a], BIN);
    }

    //writes the 4 bytes into the shift register
    digitalWrite(latchPin, LOW);
    for (uint8_t x = 0; x < numOfDaisyChainReg; x++) {
      shiftOut(dataPin, clockPin, MSBFIRST, registerVal[x]);
    }
    digitalWrite(latchPin, HIGH);

  }

}

Originally, I had if(Serial.available() > 0) and that didn't work as no LEDs lit up despite everything else in the code working as it was expected. Switching to while(Serial.available() > 0) solved that problem. Anyone have any idea why that's the case?

Turn up the warning level in File/Preferences with regard to while(Serial.available) without () , as in .available().

despite everything else in the code working as it was expected ... that may not be true

think of a sink full of dirty dishes .... if (dirtyDish.available > 0) {washDishOrNot()} , lets you go to sink, maybe wash a dish or a few, and go play ...... while (dirtyDish.available > 0) {washDishOrNot()} would have you stuck at the sink until there were no dirty dishes, or until you used an emergency escape

I'm hoping that it's just a typo, since it's not in the main listing, and answered the part I could.  And also that it doesn't just come down to not reading about  while and if.

@timemage opps it was a typo. The code section had it as 'Serial.available()' but forgot to put the '()' outside of that. My bad. I'll fix it.

@jsotola I had a feeling it'd be something like that. Curious to what ends/breaks that if(Serial.available() > 0) statement. Based on the logic of the code, I should finish the for loop inside before the if serial statement ends. By finishing the for loop, the shift register should be able to output to the LEDs.

the if statement checks availability of data ... you can assemble the received bytes in a buffer, if you want, or do nothing at all ... you would check each byte for end-of-data value ... normally a newline '\n' ... when end-of-data is received, you process the buffer .... the thing is, you could do other tasks when receiving serial data

@jsotola Let's say if I wanted to use if(Serial.available() > ) instead of `while' so the arduino does other tasks while receiving the int number I put in. What lines of code would I need to add to make it work like it was before?

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

@jsotola. Thanks! It was an interesting read. I'll implement it into my code for testing :)

I figured out why while(Serial.available()>0) and if(Serial.available() > 0) would or would NOT work in terms of my shift register code. It has to do with the serial monitor line feed and carriage return setting! If it isn't set to no line ending, it will either not register the input number or reset it back to zero right after the input is read. Learned to always check the line return option in the serial monitor! With this solved, the original question is nothing more than a general if vs while statement; which I already know the answer.
Thanks to everyone who contributed to this question! It did help me understand a lot more about Serial.available() in general. @jsotola gave a really good article. Combined with this YouTube video, it makes a lot more sense now.

Some implementations of the Arduino core have features that need loop() to exit regularly.  Although it's not often used, the serialEvent() is an example of one such thing, at least in the AVR Arduino core.
The ESP8266 Arduino core appears to do some task scheduling when loop() exits, among other things.
For your particular use case, it may make no difference at all, probably doesn't.  It may not even generate different code once compiled.  If you were doing something where you could not afford to exit loop(), run other stuff and re-enter loop() to run your code for a second pass, then there might be a performance reason to use your own while loop inside loop().  In your code as it currently is, the eventual blocking on Serial writes will end up limiting the execution to the same speed.

I'm a bit confused here. So you're saying there is a chance loop() function exiting/ending and that might break the code if using the if(Serial.available())?

I'm not sure I understand your question, and it seems like I should if the answer to it were anything other than "no, that wasn't what I was saying."  Since replacing the while in your code with an if results in loop() exiting more frequently, since that is the difference, and you asked "On what conditions would you choose one over the other?", that is what I addressed.  It's the best interpretation of your question that I could come up with.

Okay I get it now. Seems to me that the if statements doesn't behave as I'd expect it to when it's paired with the Serial.available(). It might exit pre-maturely.

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


text:
Adding another flow sensor to sketch
Adding another flow sensor to sketch
I have a water flow sketch I use for my freshwater consumption.  I would like to adapt it to use for diesel fuel consumption.  The difference is with a diesel motor the fuel pump sucks more fuel than it burns from the fuel tank and simply returns the excess to the fuel tank.  ie there are 2 hoses from the fuel tank, one to the motor, and one back to the tank.  The difference between what went to the motor and what went back to the tank is how much fuel the motor burned.
So my plan is to have 2 flow sensors (Yf-s201), and subtract the out put of one from the other and print the difference.
I have a sketch that already works to print L/m and total L.  For one sensor on PIN D2.
I have defined another sensor on PIN D3.
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  //11 = digital pin 3
byte sensorPin2       = 3;

My first road block is to print them individually. as is they both just add to a single total.
I have tried to just copy bits of code and add a "2" but I really don't have any programing knowledge so I am just stabbing in the dark.   I don't understand how to call upon the value the code has calculated.
This is the whole sketch:
/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code.
Connect Vcc and Gnd of sensor to arduino, and the
signal line to arduino digital pin 2.

 */
// include the library code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  // 1 = digital pin 3
byte sensorPin2       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 7.55;  //biger more / min

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

void setup()
{

  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
lcd.init();
lcd.backlight();
     lcd.begin(16, 2);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("S.V. SAVANNAH");
   lcd.setCursor(0,1);
   lcd.print("DAY TANK FLOW METER");

  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached

  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;

    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;

    unsigned int frac;

    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.println("mL");
    Serial.print("\t");       // Print tab space
  Serial.print(totalMilliLitres/1000);
  Serial.print("L");

      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print(int(flowRate));  // Print the integer part of the variable
      lcd.print("L/min ");

    // Print the cumulative total of litres flowed since starting
    lcd.setCursor(2,1);
    lcd.print("Total ");
  lcd.print(totalMilliLitres/1000.00);
  lcd.print("L");

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}'''

Your code currently does not use the second flow sensor. I guess you have problems in designing the code, so I try to walk you trough.
First let's look at the prerequisites, that are needed for the two flow sensors. You already have defined the pins of the flow sensors. You are also defining the number of the corresponding interrupts. In fact you don't have to do that. You can easily get the number of the interrupt through the function digitalPinToInterrupt(pin). So we are left with the pin definition. I would suggest using clearer names:
int flow_out_pin = 2;
int flow_in_pin = 3;

flow_out meaning leaving the tank, flow_in coming back into the tank.
Then in setup() we need to initiate the pins. You have this
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);

This can be then made shorter in one line per sensor:
pinMode(flow_out_pin, INPUT_PULLUP);
pinMode(flow_in_pin, INPUT_PULLUP);

Now we attach the interrupts to the pins:
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

I used the mentioned function to get the interrupt number and changed the name of the ISR. Here comes a different principle, than your firstly intended way: I would let the sensors count in their own ISR and own variables and only calculate the difference to display it. For that we need to define our 2 ISRs:
void flowOutPulseCounter()
{
    flowOutPulseCount++;
}
void flowInPulseCounter()
{
    flowInPulseCount++;
}

The count variables of course need to be defined (globally at the top of the sketch):
volatile byte flowOutPulseCount = 0;
volatile byte flowInPulseCount = 0;

Now we have left the code in loop(), which calculates flowrate, fill level and such and displays them. First: When handling interrupt data in the main code, you want to absolutely minimize the time spend with the interrupts deactivated (since in that time you might miss pulses and thus introduce errors). Normally you would just copy the data into local variables, turn on the interrupts again and do the calculation with the local variables. Something like this (inside the millis() if statement):
// Detach interrupts
detachInterrupt(digitalPinToInterrupt(flow_out_pin));
detachInterrupt(digitalPinToInterrupt(flow_in_pin));

// copy pulse count variables
byte local_flow_out_count = flowOutPulseCount;
byte local_flow_in_count  = flowInPulseCount;

// reset pulse counter variables
flowOutPulseCount = 0;
flowInPulseCount = 0;

// Reattach interrupts
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

// Do calculations using above local variables and display the results
...

For the calculations you would then calculate a flow rate and the total flow from each pulse count. With that you can then calculate the total net flow and the fill level.
Note: You might wanna change the variable type for the counters to unsigned int to get a greater margin, before they overflow, since that would mean incorrect results and it doesn't hurt you to use it.

Thanks for the great response.  I have worked through your suggestions, and I have got as far as:
void flowOutPulseCounter()
{
flowOutPulseCount++;
}
void flowInPulseCounter()
{
flowInPulseCount++;
}
But I get "a function-definition is not allowed here before '{' token" error. Which I don't really even remotely understand.

That means either you have put these functions into another function, which is wrong, or you have mismatched curly braces in the code above these functions

As chrisl already provided a very good answer, I am just adding some
notes here to complement it.
The variable pulseCount is only 8-bits. It will overflow if the flow
rate gets above 33.7 L/min. If the possibility exists that the
actual flow exceeds this rate, then, as pointed out in chrisl's answer,
you should use a 16-bit counter. If, on the other hand, you are sure
that this value cannot be exceeded, then you can keep an 8-bit counter,
and benefit from the fact that accesses to 8-bit values are atomic.
This means you do not need to ever disable interrupts:
// In global scope:
byte oldPulseCount;

// Within loop(), once per second:
byte newPulseCount = pulseCount;  // atomic read
byte pulseCountDifference = newPulseCount - oldPulseCount;
oldPulseCount = newPulseCount;  // save current value

then you compute the flow rate from pulseCountDifference. Note that
overflows of pulseCount are harmless, as the difference
newPulseCount - oldPulseCount wraps modulo 256 to the correct value.
Note also that pulseCount is never reset, as doing so could lead to
miscounting whenever an interrupt fires after pulseCount is read but
before it is reset.

// Note the time this processing pass was executed. Note that because
// we've disabled interrupts the millis() function won't actually be
// incrementing right at this point, but it will still return the value
// it was set to just before interrupts went away.
oldTime = millis();

This comment is wrong. The statement detachInterrupt(sensorInterrupt)
disables only an external interrupt. It does not disable interrupts
globally, and specifically does not disable the timer interrupt that
increments millis(). There is therefore no guarantee that the various
calls to millis() will return the same value within one iteration.
Instead, millis() should be called only once, and its value
remembered:
void loop()
{
    unsigned long now = millis();  // save this value
    if (now - oldTime >= 1000) {
        // ...
        oldTime = now;
    }
}

Note that I use >= for checking the delay: with the > operator the
period is at least 1001 ms.

flowMilliLitres = (flowRate / 60) * 1000;

This is incorrect. It should be
flowMilliLitres = (flowRate / 60) * (now - oldTime);

for the same reason that now - oldTime is used in the computation of
flowRate. It may be noted that this can be simplified to
flowMilliLitres = (1e3/calibrationFactor/60) * pulseCountDifference;

as the factors now - oldTime cancel out.


text:
Where is the documentation for writing an Arduino core?
I'm interested in writing an "Arduino core" (i. e. porting Arduino to a new MCU and new board(s)).  I'm having trouble finding much documentation on how to do so.  Am I missing something?
This page says "anyone may develop a core for their own boards following the rules and requirements we have issued."  So, where are those "rules and requirements?"
I found something called the "Platform Specification", which sounded promising, but it only documents the config files; it does not say anything about the code that needs to be written to support a new platform.
I found ArduinoCore-API, which says it is the "hardware independent layer of Arduino core."  But it doesn't mention anything about how to write the hardware-dependent part of the core.
I'd be grateful if anyone could point me to the Arduino core documentation.  It's not turning up in my web searches.  Thanks!
Clarifications:

Yes, I can look at existing cores as examples, but I'd rather have the documentation, as well.  Especially since existing cores may be of varying quality, or may not be up to the latest standard.  Documentation is always a good thing.
The reason I want to write a core is because... I want to use an MCU which is not currently supported!  (Specifically, I want to add support for the GD32F350, but really that shouldn't be relevant to answering "Where is the documentation?")

the specification you linked is all what you need. see existing cores as examples. why do you want to create a core?

The specification doesn't say anything about the code I need to write.  Where does it specify that?

I understand. The Arduino API is described here https://www.arduino.cc/reference/en/. some parts are implemented in Arduino API repository. some depend on the hardware and must be implemented.

99% of writing a core is understanding, and coding for, the chip that you are working with. The specification cannot tell you that, since it completely depends on the chip architecture. You basically have two options: 1. use the pre-defined API layer and fill it out with your code behind it to make the functions work, or 2. write your own code that implements the API functions. The documentation is the list of API functions. It cannot tell you how to write those functions.

some new Arduino cores for ARM MCUs are made on top of ARM mbed OS and use the mbed support for the MCU

There are two major parts to writing an Arduino core: the hardware independent portions and the hardware dependent.
The hardware independent portions are pretty much done for you in the ArduinoCore-API. However I wouldn't just use that verbatim but use it as a starting point and adapt it to your needs. This is because it actually has a couple of unresolved issues and not everything may 100% fit your needs. We don't use it for the chipKIT core because:

It has an unresolved issue around the naming of the String.h file which conflicts with the libc's string.h on case insensitive filesystems
Our USB stack is vastly different to how the Arduino "Pluggable USB" works
We have extra facilities in a number of standard objects to make use of more efficient use of more advanced hardware

Once you have the hardware independent portion sorted you need to write, from scratch, the hardware dependent portion.  The basic list of functions you need to implement are listed in the Arduino reference. How you write them cannot be documented, since that depends on the hardware. And you may well need to (or want to) write considerably more functions that just those. For example on chipKIT as well as the standard analogWrite() function we also have functions to change the PWM frequency and resolution - things that aren't part of the "standard", but are incredibly useful.
A good starting point is to examine the Arduino.h file of an existing core (the AVR core is a good baseline) which will list most of the functions and their parameter/return types. That gives you what the functions expect to receive and what they should emit, but how those functions are written is completely down to you.
And then of course you have to implement the boards variants etc to make the whole things work...
Also, be warned that writing (and maintaining) a core is a long and involved process and will consume the rest of your life.

Thanks!  I guess it's a lot more obvious than I thought, in that you're directly implementing the API, rather than implementing some sort of "backend" functions that are called by the API.  Still, some sort of "10,000 foot overview" doc would have been helpful.  I'm not as worried about the "how", because I plan to just call into the chip vendor's firmware library.


text:
Parsing read SD file into 2 variables
Recently I started some tests controlling water heater with temperature sensor data as described in detail here
So far I've been testing a small dataset to control water temperature that is quite easy to write down by myself.
#include <NTPClient.h>
#include <WiFi.h>
#include <WiFiUdp.h>

//WiFi Conf
const char *ssid     = "ssid_addr";
const char *password = "wifi_password";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
unsigned long current_time;

// Sensors Conf (fixed value just to test relay response)
float temperature = 30.5;

//Relay Conf
const int relay = 26;

struct SetPoint {
  unsigned long time;
  float temperature;
};

#define DATA_SIZE  8

SetPoint scen1[DATA_SIZE] = {
  {1616952559, 32.4},
  {1616952739, 10.2},
  {1616952859, 10.4},
  {1616952867, 40.2},
  {1616952927, 20.4},
  {1616952928, 35.2},
  {1616952945, 22.4},
  {1616952947, 28.2}
  };

unsigned int pos = 0;

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

  pinMode(relay, OUTPUT);

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

  timeClient.begin();

}

void loop() {
  timeClient.update();

  long current_time =  timeClient.getEpochTime();

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    set_thermostat(/*data[pos].temperature, temperature*/);
    pos++;
  }

  Serial.println(timeClient.getEpochTime());
  Serial.println(timeClient.getFormattedTime());
  Serial.println(pos);
  delay(3000);

}

void set_thermostat() {
  if (temperature < scen1[pos].temperature) {
    digitalWrite (relay, HIGH);
  }
  else if (temperature > scen1[pos].temperature) {
    digitalWrite (relay, LOW);
  }
}

But now I'm planning to use a larger file with different datapoints and an option is to store them in a sdcard and, then, the microcontroller parses each line to control the temperature with an interval of three hours.
There will be about 720 lines with the following structure ("Scen" is the temperature simulation scenarios that will be the reference to turn the relays on or off):
    Time,UNIX,Scen1,Scen2,Scen3
    21/04/2021 00:00:00,1618963200,"27.45","29.01","30.85"
    21/04/2021 21:00:00,1619038800,"26.16","27.82","29.75"
    21/04/2021 06:00:00,1618984800,"25.28","26.83","29.02"
    21/04/2021 09:00:00,1618995600,"24.62","26.49","28.51"
    21/04/2021 12:00:00,1619006400,"27.19","29.47","29.53"
    21/04/2021 15:00:00,1619017200,"30.65","34.07","30.50"
    21/04/2021 18:00:00,1619028000,"31.87","35.78","31.78"
    21/04/2021 21:00:00,1619038800,"30.43","35.20","30.88"
    22/04/2021 00:00:00,1619049600,"28.45","31.86","29.47"

The problem is that it is hard to find out how to parse data from the file into two variables (UNIX Time and temperature), for each temperature scenario, as used here:
struct SetPoint {
  unsigned long time;
  float temperature;
};

#define DATA_SIZE  8

//scenario 1 array
SetPoint scen1[DATA_SIZE] = {
  {1616952559, 32.4},
  {1616952739, 10.2},
  {1616952859, 10.4},
  {1616952867, 40.2},
  {1616952927, 20.4},
  {1616952928, 35.2},
  {1616952945, 22.4},
  {1616952947, 28.2}
  };

Is there an effective way to get what I'm looking for?

You can read the file line by line (surely that is rather easy to find with google). Then you can use strtok() on the resulting c-string (please avoid the String class). Note that strtok alters the c-string. Please try googling for a strtok tutorial and try it out. Maybe that is already what you need. (strtok is a bit difficult to understand at first, but it is a really good way to tokenize a string)

Thanks! Yeah, I managed to read line by line and today will go deep on strtok(). I update this question when I advance on it.


text:
Can't read data from registers using I2C
I am trying to read data from the registers 6, 7, 8 and 9 of the STC3100 (Data Sheet) using an arduino uno.
I followed this tutorial: https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/ And adjusted the device and register adress accordingly.
This isn't working and instead of returning the data on the register I'm just getting 16 over and over again.
Here is my code:
#include <Wire.h>
int ADXLAddress = 0x70;

#define X_Axis_Register_DATAX0 0x08

#define X_Axis_Register_DATAX1 0x09

#define Power_Register 0x00

int X0,X1,X_out;

void setup() {

  Wire.begin();

  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXLAddress);
  Wire.write(Power_Register);
  Wire.write(16);
  Wire.endTransmission();
}
void loop() {
  delay(2000);
  Wire.beginTransmission(ADXLAddress);

  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);

  Wire.endTransmission();

  Wire.requestFrom(ADXLAddress,2);

  if(Wire.available()<=2) {
    X0 = Wire.read();
    X1 = Wire.read();
  }

  Serial.print("X0= ");
  Serial.print(X0, BIN);
  Serial.print("   X1= ");
  Serial.println(X1, BIN);
}

Please include your code into your question (by editing it)

I'm not sure, but from reading the data sheet I would expect, that only one Register address must be written, than read the two bytes; the register address will be auto incremented, it seems. You code writes register adress 8, then 9 and I would say, you start reading from reg address 9 then auto increment to 10 (9=battery Voltage High reg 10 = Temperature low reg). The data sheet could also be interpreted as writing more than one register address without reading data, is not specified.

The following code shows, how I would read from a STC3100. But I own none of them, so I can not try the code. I would be very surprised if it works directly. Use it as an example. Perhaps we could improve it together. ;-)
#include <Wire.h>

#define STC_ADDRESS 0x70
#define MODE_REGISTER 0x00
#define CURRENT_LOW_REGISTER 0x06
#define VOLTAGE_LOW_REGISTER 0x08

int voltage, current;
int high_value = 0;

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

  Wire.begin();
  delay(100);
  // power on the STC
  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(MODE_REGISTER);
  Wire.write(16);
  Wire.endTransmission();
}

void loop()
{
  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(VOLTAGE_LOW_REGISTER);
  Wire.requestFrom(STC_ADDRESS, 2);
  delay(500);
  if( Wire.available() > 0 )
  {
    voltage = Wire.read();
    //Serial.print("REG 8 = ");
    //Serial.println(voltage);
  }
  delay(500);
  if( Wire.available() > 0 )
  {
    high_value = Wire.read();
    //Serial.print("REG 9 = ");
    //Serial.println(high_value);
    voltage += (high_value << 8);
    //Serial.print("voltage = ");
    //Serial.println(voltage);

  }
  Wire.endTransmission();

  Wire.beginTransmission(STC_ADDRESS);
  Wire.write(CURRENT_LOW_REGISTER);
  Wire.requestFrom(STC_ADDRESS, 2);
  delay(500);
  if( Wire.available() > 0 )
  {
    current = Wire.read();
    //Serial.print("REG 6 = ");
    //Serial.println(current);
  }
  delay(500);
  if( Wire.available() > 0 )
  {
    high_value = Wire.read();
    //Serial.print("REG 7 = ");
    //Serial.println(high_value);
    current += (high_value << 8);
    //Serial.print("current = ");
    //Serial.println(current);
  }
  Wire.endTransmission();

  Serial.print("V= ");
  Serial.print(voltage);
  Serial.print("   C= ");
  Serial.println(current);
}

I tried the code you posted and currently it won't print anything if I run the whole code. If I run it so that it only reads registers 8 and 9, it will print a value (which is incorrect) once and then stop, as if it isn't looping at all.

I looked over the code and found some errors. I changed the code with the fixed version. I made an error with the first #define macro that should have prevented the code from compiling. How did you compile it? Have you fixed the macro? If there is no hardware error, this version should at least read the registers. I have included some ''Serial.println` you can uncomment, to see the raw register values. If it will stop again, you can see where.

Seems to be working well at the moment. Thank you so much for your help :)


text:
Interfacing SPI (MCP3903)
I'm trying to interface MCP3903. I haven't really don't any SPI interfacing before and I can't seem to find clear enough answer for newbs. Please bare with me.
I'm trying to use this library. http://www.kerrywong.com/2014/05/10/mcp3903-library/
On the website there is the following circuit diagram.

I can see SDI, SDO pins on the ESP module, how do I connect the SCK and CS pins? If they can be any pins how do I declare them on the test program on the website?
Thank you

Which ESP module are you using?

it's wroom ESP-32

SPI0 and SPI1 are used internally to access the ESP32’s attached flash memory. SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users.
A quick google search shows:

So you can use IO5, IO18, IO19 and IO23.


text:
TRT-25 and Arduino Uno
I am reaching out for help on a project I am working on. We are trying to integrate a reaction torque sensor and I am having a hard time deciding how to go about it. Previously I assumed that like my load cell I would be able to use the HX711 module to connect my Torque sensor to my Arduino. The Torque sensors uses a Wheatstone bridge configuration, which is great for this module. The problem I ran into is that the TRT-25 Torque sensor requires an excitation voltage of 10V and my Arduino is only supplying 5V. When I tried powering my sensor separately with 10V I quickly found out that these HX711 modules are not designed to handle 10V...
Needless to say that I am now wondering how I should be power my sensor, but also which A/D converter can be used to get this working. The same manufacturer sells all the components to get this working, but it is hundreds of dollars more and our budget doesnt allow for it. I am posting links here so you can see the sensor. What I am considering now is finding a 10V source and connecting the signal pins to my analog pins on my Arduino. I am hoping based on the raw value I can compute a torque measurement based upon this small piece of information their tech support gave me.  (X mv/v * EXCITATION v = TORQUE in/lbs).
FYI, I dont have much more information outside of what it is on the site for the sensor. My project uses a small enclosure and I have a arduino proto shield to power my other 3 sensors. I am limited on space but could probably incorporate a small supply and replace the current HX711 module.
HX711
https://www.transducertechniques.com/trt-torque-sensor.aspx

your question has nothing to do with the arduino ... it belongs at https://electronics.stackexchange.com/questions ... please delete the one here

"When I tried powering my sensor separately with 10V I quickly found out that these HX711 modules are not designed to handle 5V"  Did you mean not designed to handle 10V?  It would probably be better to link to exactly what you have.

It doesn't require 10V. 10V is just the voltage that they performed the calibration at. You can use anything up to the maximum - though at anything other than 10V your accuracy may vary slightly.

@Majenko I am finding that the mV reading seems to be too low. Less than 0.1mV it seems. I am planning on trying again with 9V battery.


text:
Stm32 Blue Pill Internal reference voltage Arduino IDE
I want to use the internal reference voltage (1.2V) of stm32f103 blue pill using Arduino IDE. I searched the whole internet but couldn't find anything. I need help with this. Thanks.

Did the whole internet include the datasheet for the chip?

Link to the core you're using, please. It should implement analogReference(INTERNAL) or something similar.

Maybe this will help a little: http://www.efton.sk/STM32/STM32_VREF.pdf (usualy it can be used to compute VREF+ or VDDA, as it can't be used directly as ADC reference)

And (different family, but it should be similar) https://community.st.com/s/question/0D50X00009XkePgSAJ/use-adc-with-internal-vref-stm32l151

There's no way of using the internal 1,2v reference as the ADC reference. (in the same way that you can do on an AVR)
You can only use the ADC to read the internal vref, and use that value to adjust the next ADC reading you take. Like a compensation factor.


text:
Sparkfun Spectrum Shield no change in frequency
So i wanted to build a music visualizer using a MSGEQ7. As I just got started with electronics, I did some soldering beforehand and I think I am doing okish. While it might not be perfect, the contact should be fine.
I hooked my arduion MEGA 2560 Board up with the Spectrum Shield and ran the code according to this webpage
https://learn.sparkfun.com/tutorials/spectrum-shield-hookup-guide/all
My solders are fine, however, the serial output for the 7 freuquency bands never changes and stays at 150 once I plug in an aux cable. I checked if the audio is processed at all by connecting a speaker to the output and the music does play. However, there are no changes of the frequency bands when playing music.
Is my board broken? If needed, i can provide pictures of my soldering/circuit. I got pretty frustrated cause I am just getting started and I don't even know how to tell what's wrong.
I really appreciate any help.
Thanks!

please add your code to your post


text:
ESP8266 + 4x TM1637 == possible?
I'm having trouble getting my NodeMCU connected to 4 x 4 Digit 7 Segment Displays.
So far I've been able to connect 2 & get them to display things from the demo repository.
However, after trying all possible combinations of different pins & looking up the pinout reference I have no idea why I can't get them to work.
Any help would be greatly appreciated.
I'm working with:

ESP8266 NodeMCU ESP-12E (CP2102)

4 Digit 7 Segment Display (TM1637)

As suggested @romkey:
#include <Arduino.h>
#include <TM1637Display.h>

// Module connection pins (Digital Pins)

#define CLK_1 D2
#define DIO_1 D3

#define CLK_2 D5
#define DIO_2 D6

#define CLK_3 13
#define DIO_3 15

// The amount of time (in milliseconds) between tests
#define TEST_DELAY   500

TM1637Display display1(CLK_1, DIO_1);
TM1637Display display2(CLK_2, DIO_2);
TM1637Display display3(CLK_3, DIO_3);

void setup()
{
}

void loop()
{
  int k;
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
  uint8_t blank[] = { 0x00, 0x00, 0x00, 0x00 };
  display1.setBrightness(0x0f);
  display2.setBrightness(0x0f);
  display3.setBrightness(0x0f);

  // Brightness Test
  for(k = 0; k < 4; k++)
    data[k] = 0xff;
  for(k = 0; k < 7; k++) {
    display1.setBrightness(k);
    display1.setSegments(data);
    display2.setBrightness(k);
    display2.setSegments(data);
    display3.setBrightness(k);
    display3.setSegments(data);
    delay(TEST_DELAY);
  }
  while(1);
}

I've tried addressing the CLK_3 & DIO_3 pins as "Dx" but that didn't work as well.
Repos used:

https://github.com/avishorp/TM1637

There’s a lot that can go wrong here. If you share exactly how you connected the most likely to work circuit and a minimal viable example of the code that doesn’t work, someone will be more likely to help you.

use one clock pin for all. avoid boot config pins D3,D4,D8 and RTC pin D0

Try one display at a time but on different pins to make sure that your selection works at all. Only after success merge all together.


text:
Arduino Uno's Timer maximum frequency using Timer Compare Interrupt, not Timer Output Pins (e.g. OC0A)
I want to achieve the generation of a custom binary signal over a digital pin at the highest possible frequency on Arduino Uno.
Using Timer's output pins (e.g. OC0A), one can get a pin to toggle at a maximum frequency of 16MHz (which corresponds to a sqaure wave of frequency 8MHz), as described here:
Maximum frequency of digital signal in Arduino Uno?
However as far as I understand, Timer's output pins are only useful if one needs to generate a repetitive waveform such as a PWM or square wave, so it cannot serve my purpose which requires the generation of a custom binary signal.
Using the following code, I was expecting digital pin 9 to toggle at a frequency close to 16MHz too, since I use no prescaler and set the Compare Match Register value to 0:
void setup()
{
    DDRB = 1 << 1;  // Set D9 as OUTPUT

    cli();
    TCNT0 = 0; TCCR0A = 0; TCCR0B = 0;
    TCCR0A |= (1 << WGM01);  // CTC mode
    TCCR0B |= (1 << CS00);  // no prescaling
    OCR0A = 0;  // Highest timer overflow frequency possible
    TIMSK0 |= (1 << OCIE0A);
    sei();
}

ISR(TIMER0_COMPA_vect)
{
    PORTB ^= 1 << 1;  // Toggle D9; this allows to measure the toggle frequency, however this could be replaced by some code to generate a custom binary signal
}

void loop(){}

However in fact it appears to toggle at a frequency of only approximately 410kHz (which corresponds to a square wave of frequency 205kHz), as the below image shows:

I used Timer0 but I get the same frequency with Timer1 and Timer2.

How can one explain that using this code I get this toggle frequency on the digital pin ?
How can I generate a custom binary signal over a digital pin at the highest possible frequency ?

I realize this is peanuts compared to the greater issues which are outlined in Majenko's answer, but if you do want to toggle PB1, you can PINB = 1 << 1; rather than PORTB ^= 1 << 1 to save a couple of cycles.  The construction may look weird, but they've designed the AVR GPIO hardware so that you can toggle pin be writing 1 bits to their bit positions in the PINx registers; writing 0-bits have no effect.  If you take the writing in a tight loop outside of an interrupt suggestion, this may have some impact.

Thanks, I didn't know you could do it more efficiently that way; this would be impactful in some situations indeed.

How can one explain that using this code I get this toggle frequency on the digital pin ?

Code takes time to execute. Your ISR, when compiled, looks like:
ISR(TIMER0_COMPA_vect)
{
 124:   1f 92           push    r1
 126:   0f 92           push    r0
 128:   0f b6           in  r0, 0x3f    ; 63
 12a:   0f 92           push    r0
 12c:   11 24           eor r1, r1
 12e:   8f 93           push    r24
 130:   9f 93           push    r25
    PORTB ^= 1 << 1;  // Toggle D9; this allows to measure the toggle frequency, however this could be replaced by some code to generate a custom binary signal
 132:   85 b1           in  r24, 0x05   ; 5
 134:   92 e0           ldi r25, 0x02   ; 2
 136:   89 27           eor r24, r25
 138:   85 b9           out 0x05, r24   ; 5
}
 13a:   9f 91           pop r25
 13c:   8f 91           pop r24
 13e:   0f 90           pop r0
 140:   0f be           out 0x3f, r0    ; 63
 142:   0f 90           pop r0
 144:   1f 90           pop r1
 146:   18 95           reti

That's 18 assembly instructions, each needing between 1 and 4 clock cycles to execute.  Referencing the datasheet you can count the exact cycles needed and sum them up, yielding 31 clock cycles.
Toggling at maximum speed that would be 16MHz / 31 = 516kHz.
And then you have the rest of the code running between each call to the interrupt, so it's slower than that.

How can I generate a custom binary signal over a digital pin at the highest possible frequency ?

By not using interrupts, and writing a tight loop in assembly language.

How did you get the exact assembly out? Is it possible to do that with the Arduino IDE or did you have to use the Atmel IDE?

That actually addresses the question quite well.
My understanding of what is happening is the following: the first Timer Compare Interrupt occurs. Before the ISR has finished running, a second Timer Compare Interrupt occurs, but is queued because the previous ISR has not finished running. As soon as the first ISR has finished running, the second ISR is allowed to run. And that goes on and on is such a way that the ISR is running at a frequency equal to (or at least close to) the inverse of its duration.
What do you say about this interpretation?

How can I use assembly language to achieve a higher toggle frequency than with the Timer Compare Interrupt ? In fact, how can I use assembly language to achieve my goal without using a timer interrupt (which as you showed is slow)?

@Tri I used avr-objdump -S <filename.elf> on the compiled elf file from the Arduino IDE (actually arduino-cli as I hate the IDE).

@Ramanewbie That's a good interpretation, yes. Writing assembly language can be a bit of a black art. You would need to code delay loops to get the timing you want, along with toggling of the IO pin and looking up of the data sequence. Not a fun task. Another option could be to stream the data out using the SPI port, where the speed will be relative to the resolution you desire - maximum 8 MBits/s (4MHz square wave)

"You would need to code delay loops to get the timing you want, along with toggling of the IO pin and looking up of the data sequence"

With that approach, you would need to count the number of clock cycles that your IO tasks take to execute, in order to deduce by substraction the duration needed for the delay loop so as to get the wanted operation frequency, right ?

@Ramanewbie That is correct, yes.

Let us continue this discussion in chat.


text:
How do I measure the analog PPG signals from my Arduino Nano that's wired up to the Heart Rate 3 Clicker
I'm trying to find a code that would take the PPG signals from the MIKROE-2036 Heart Rate 3 Clicker and process the information through the Arduino Nano to find a person's Oxygen Saturation. Basically, by using this code how do I measure Oxygen Saturation from the given analog inputs from the LEDs?
This is the test code that the Arduino Nano could use, but it's more of a template:
/*
 * AFE4404 Basic Read library example.
 * https://github.com/rakshithbk/AFE4404-Library
 *
 * On Arduino Uno -  | AFE4404 | Uno Pin
 *                   | I2C_Dat | A4
 *                   | I2C_Clk | A5
 * get_led_val() will return uint32_t values.
 *
 * Advanced - you can modify the sample period and other
 * parameters in the library files (refer AFE4404 datasheet)
 */

#include <Wire.h>
#include <AFE_connect.h>

AFE A;

void setup() {
  Serial.begin(115200);
  Serial.println("AFE4404 basic readings -\n");
  A.init();
}

void loop() {
  Serial.print("LED 1 Val = ");
  Serial.print(A.get_led1_val());
  Serial.print("\t LED 2 Val = ");
  Serial.print(A.get_led2_val());
  Serial.print("\t LED 3 Val = ");
  Serial.print(A.get_led3_val());
  Serial.println();
}

This is the library I found that uses the Heart Rate 3 Clickers LEDs: https://github.com/rakshithbk/AFE4404-Library

The code above already measures the PPG signal. I don't know the sensor, that you have. But most likely taking just the signal from the first LED (with the corresponding function) will get you the PPG signal. I guess your real question is about how to calculate SPO2 (Oxygen Saturation) from the LED signals. Have you tried googling for that? I don't know that, so I would also just google for it.

@chrisl The sensor I'm using is the MIKROE-2036 Heart Rate 3 Clicker and essentially what you asked is exactly what I've been trying to look for. Basically, by using this code how do I measure Oxygen Saturation from the given analog inputs from the LEDs? I tried searching for that answer for nearly a month and haven't gotten close.


text:
How to use an Arduino along with a PPG sensor to find respiration rate
I am working on a project where I am trying to determine respiration rate through an Arduino Nano and a MikroE Heart Rate 3 Click device.  I have been working on this for a few months, reading different research papers attempting to find an algorithm that would give me respiration rate values, but am having trouble finding an algorithm that both does what I need and encode it into the Arduino.  Does anyone know of a code that would work?
I have so far have only the basic code that reads the PPG values, but it does not provide me with the Respiration rate values.  This is the code I have so far:
/*
 * AFE4404 Basic Read library example.
 * https://github.com/rakshithbk/AFE4404-Library
 *
 * On Arduino Uno -  | AFE4404 | Uno Pin
 *                   | I2C_Dat | A4
 *                   | I2C_Clk | A5
 * get_led_val() will return uint32_t values.
 *
 * Advanced - you can modify the sample period and other
 * parameters in the library files (refer AFE4404 datasheet)
 */

#include <Wire.h>
#include <AFE_connect.h>

AFE A;

void setup() {
  Serial.begin(115200);
  Serial.println("AFE4404 basic readings -\n");
  A.init();
}

void loop() {
  Serial.print("LED 1 Val = ");
  Serial.print(A.get_led1_val());
  Serial.print("\t LED 2 Val = ");
  Serial.print(A.get_led2_val());
  Serial.print("\t LED 3 Val = ");
  Serial.print(A.get_led3_val());
  Serial.println();
}

You are basically asking the same thing, as the question before yours, which was asked by a different user. That's unusual in such temporal proximity. Are you somewhat related?

Yes our projects are related, as we are actually working together along with one other member.  However, while the other question asks about finding oxygen saturation from the sensor, I am focusing on how to find the respiration rate.  We have the initial code to get a reading but each need an individual algorithm with which we can determine the different measurements from those initial signals.


text:
Code for Heart Rate Detection using PPG Sensor
I am using the "MIKROE Heart Rate 3 click" PPG sensor (https://www.mikroe.com/heart-rate-3-click) and an Arduino Nano (https://store.arduino.cc/usa/arduino-nano) to find heart rate estimation. Does someone know what code to use?
The library associated to the MIKROE is unavailable, therefore, I tried using the AFE4404 library through the code shown below and running a separate algorithm for finding heart rate, however, once I ran it, the monitor and plotter do not provide any peaks that must be used to run the algorithms.
PPG TEST CODE (used previously but do not know how to find heart rate)
/*
 * AFE4404 Basic Read library example.
 * https://github.com/rakshithbk/AFE4404-Library
 *
 * On Arduino Uno -  | AFE4404 | Uno Pin
 *                   | I2C_Dat | A4
 *                   | I2C_Clk | A5
 * get_led_val() will return uint32_t values.
 *
 * Advanced - you can modify the sample period and other
 * parameters in the library files (refer AFE4404 datasheet)
 */

#include <Wire.h>
#include <AFE_connect.h>

AFE A;

void setup() {
  Serial.begin(115200);
  Serial.println("AFE4404 basic readings -\n");
  A.init();
}

void loop() {
  Serial.print("LED 1 Val = ");
  Serial.print(A.get_led1_val());
  Serial.print("\t LED 2 Val = ");
  Serial.print(A.get_led2_val());
  Serial.print("\t LED 3 Val = ");
  Serial.print(A.get_led3_val());
  Serial.println();
}

GitHub
rakshithbk/AFE4404-Library
Basic Library of AFE4404 for Arduino Uno. Contribute to rakshithbk/AFE4404-Library development by creating an account on GitHub.


text:
Arduino NRF24LO1
I have a problem with transmiter (Arduino uno) and receiver (Arduino nao). When I am trsmiting that I receive that:
An this is my code for receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define CE_PIN  7
#define CSN_PIN 8

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
bool newData = false;

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

    void setup() {

        Serial.begin(9600);

        Serial.println("SimpleRx Starting");
        radio.begin();
        radio.setDataRate( RF24_250KBPS );
        radio.openReadingPipe(1, thisSlaveAddress);
        radio.startListening();
    }

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

    void loop() {
        getData();
        showData();
    }

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

    void getData() {
        if ( radio.available() ) {
            radio.read( &dataReceived, sizeof(dataReceived) );
            newData = true;
        }
    }

    void showData() {
        if (newData == true) {
            Serial.print("Data received ");
            Serial.println(dataReceived);
            newData = false;
        }
    }

and transmitter
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define CE_PIN  7
#define CSN_PIN 8

const byte slaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

char dataToSend[10] = "Message 0";
char txNum = '0';

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

void setup() {

    Serial.begin(9600);

    Serial.println("SimpleTx Starting");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}

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

void loop() {
    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        prevMillis = millis();
    }
}

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

void send() {

    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        // Always use sizeof() as it gives the size as the number of bytes.
        // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("Data Sent ");
    Serial.print(dataToSend);
    if (rslt) {
        Serial.println("  Acknowledge received");
        updateMessage();
    }
    else {
        Serial.println("  Tx failed");
    }
}

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

void updateMessage() {
        // so you can see that new data is being sent
    txNum += 1;
    if (txNum > '9') {
        txNum = '0';
    }
    dataToSend[8] = txNum;
}

Do you see an error?


text:
Converting an int to an unsigned char for display on a Nokia 5110
I've been working on a small project getting some images displayed in a Nokia 5110 screen via an Arduino. I've been getting it working, but one of the issues I have is that I would like to have a list on integers and convert that an unsigned char array that the display requires. Generally I have something like this which works out of the box.
unsigned char src [] PROGMEM = {0x00, 0x00}

Surprisingly, I found that this also works
unsigned char src [] PROGMEM = {255, 255}

But when I have a list like this
int src [] = {255,255}

and try to convert it to an unsigned char array, things don't display correctly
unsigned char new_src[2];

for (int i=0; i<2; i++){
    new_src[i] = (unsigned char) src[i];
}

When I try to display this, it's clearly broken. I thought simply casting the int to an unsigned char would be enough (it doesn't work even if I don't cast it).
Here's how I display the array (for 84x48, the above arrays were just an example) :
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
display.drawBitmap(0, 0,  src, 2, 48, BLACK);
display.display();

On more note:
The end game is to have a file with a list of ints. I would then read that list of ints into an array and convert it into an unsigned char array and then display that.

How do you display src?

@EdgarBonet edited into the original post

What do you mean by “works”? 2. Why arrays of length 2? For an 84×48 bitmap you need an array of 528 bytes. 3. Does it still work if the PROGMEM arrays are const? 4. Why do you want to have a list of int? Other than wasting RAM, what does that give you that a list of uint8_t doesn't?

"works" as in displays the image properly. 2. This was just an example for simplicity sake. 3. Yes it still works. 4. Because I'm reading the integer values out of file. 4. My C skills aren't as sharp as your so I'm sorry for wasting RAM. @EdgarBonet

Besides mentioning it, I don't think @EdgarBonet's point was the extra RAM (or Flash), but on the fact that storing your data as 'unsigned char src [] PROGMEM' works for you - why do not use that?

@JRobert I'm unable to put them in the Arduino code at compile time. The idea is that I would read a list of ints from a file ( I have several files that I would iterate through) and convert that list to the unsigned char array on each loop iteration. If there's a way to store a unsigned char array in a file and read that directly, I could just as well do that.  I'm trying to automate the process of having to go to a website to convert my bitmap, and then copy the result into my Arduino code. I have the conversion part complete via a Python script and now I'm tryin to get it over to Arduino.

The idea is that I would read a list of ints from a file ( I have
several files that I would iterate through) and convert that list to
the unsigned char array on each loop iteration.

The file could be a stream of bytes just as well as a stream of ints (or uints). If it were, no conversion would need to be done - just read a byte & store it, read a byte & store it, ....  If instead, it is a character representation of values, "37, 150, 8, ...", again, read the characters of one value, convert them to int8_t or  uint8_t and store them in your byte array. Look up the atoi() or sscanf() functions to do the conversion.


text:
How do you count objects (using ultrasonic sensor HCSR04) as 1, after they leave the trigger/echo path?
I found a simple code online that meets my goal to almost 100%, however when I place my hand in front of it, the number continues to count. I am trying to only count "1" when the solid object has moved from initial view of the sensor, to ending view.
#define trigPin 13
#define echoPin 12
int counter = 0;
int currentState = 0;
int previousState = 0;

void setup() {
 Serial.begin (9600);
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
 long duration, distance;
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 distance = (duration/2) / 29.1;
 if (distance <= 10){
 currentState = 1;
 }
 else {

Your code is missing some part at the end. Maybe thats just a copy paste error. Please provide the full code

it's the same thing as counting the number of times a light has been turned on ....you don't count 1 every time the light is on when you look at it ... there is something else that you have to see before you can say that the light was just turned on


text:
Spectrabloom LED light box
I'm looking to make a DIY version of Dan Conrad's Spectrabloom. I've got an Arduinio Uno, a piece of code that uses PWM to randomly fade three 1w LEDs (one red, one blue and one green) and a PicoBuck LED driver.
Question is - do I have to have two power supplies? One to power the PicoBuck and one to power the Arduino or can I have them all running off one supply? If the latter - can anyone give me pointers on the way to hook everything up?

Question is - do I have to have two power supplies?

No, you can use one power supply for both. But you need to make sure, that the LED current is not flowing through the Arduino, since that can kill the Arduino. To do that, you need to connect the power supply to the LED driver and the Arduino in parallel. For example, lets assume you have bought a 5V wallwart/power supply, which is can provide enough current for your whole circuit (and some headroom for further development). Then you can connect the positive lead to the 5V pin of the Arduino and the Vin+ (positive supply voltage) pin of the LED driver. Also connect the negative lead of the power supply to ground on Arduino and Vin- (negative supply voltage) of the LED driver. That way the current for the LEDs comes directly from the power supply and doesn't need to flow through the Arduino, but past it.

Thanks Chris - I have a wallwart + splitter that I intend to run into two dc jacks connected to the Arduino and the LED driver respectively - will this work?

Yes, if it has a fitting voltage rating

Yeh, neat - it does. All good. Thanks for your help.

Three 1 Watt LED could potentially draw 600 mA total, exceeding the maximum draw for the Arduino. Each LED could draw 200 mA, exceeding (by 10x) the draw of a pin driver. So, yes, you need to supply the LEDs separately from the Arduino. Also, that driver is a constant-current driver, at 330 mA per channel. Your LEDs would prefer a constant voltage, chopped by PWM.

I haven't quite understood, why a constant-current driver would be a problem. Isn't that a quite common way to drive LEDs, especially the high powered ones? Or do you mean, that 330mA per LED would be too much? The OP didn't specify, which LEDs he uses.

If constant current is usual, I wasn't aware of it. But yes, I wouldn't choose a supply that could overdrive my devices by 50% if I let the PWM get too high. Murphy is never far away...  :)

I know constant current drivers from laser diodes (which electrically are just LEDs). I think they are commonly used in that field, because the current is what actually determines the intensity. Also you can tune the intensity more easy via current, than via voltage because of the (I think exponential) non-linear rise of the diode characteristic. In the end it should not be important, if you use constant current or constant voltage, as long as you don't overload the LED. I think that overload is the important point in your argument. You are right with Murphy.


text:
Electronics Laboratory
I would like to know if someone could explain to me how to create an arduino electronics laboratory with soldering iron etc. with a low budget <3

Go shopping on Ali Express.

https://majenko.co.uk/blog/top-6-things-every-engineer-needs

That question cannot be answered without knowing what you want to accomplish. It is like I want to go swimming in the water.  We have no idea of your skill set, what you want to build and or trouble shoot.  Your budget is less than 3 what? If $3 you could get a pad of paper and pencils.  Much more information is needed.

@Gil I thought the <3 is meant to be a heart, as emoticon at the end of the question XD But you have a point

For starters, I would avoid the soldering iron, if possible. It's much easier to work with breadboards. Soldering (modern) electronics is a skill on its own.

There won't be a really complete list, since there are many many tools, that one could use for an electronics/Arduino laboratory. Also low budget is relative, so you might wanna choose out of the below list based on your real budget and the actual price of the parts at your place. Also consider, that many tools can be bought very cheap, but these tools are often bad, which means, that you most likely will buy a better replacement product later (buying cheap means buying twice). Still a low budget can absolutely justify buying cheap at first (some bad tools is better than no tool).
Note: I will use Euro as currency here (as I'm from Germany), which can about be used interchangeably for US Dollar. Your mileage may vary.

Breadboards: For working with Arduinos you wanna first build your circuits on a breadboard for testing. You should at least get one. I've seen 3-Packs of breadboards on platforms like amazon for about 12€.

Jumper-Wires (male-male/male-female): These wires with attached dupont jacks will make it easier to prototype on breadboards.

Colored Wire spools: I have a few spools with 4 different colors of 0.2mm² wire. You can use these for your PCBs and for breadboards. The different colors help to color code your wires for better overview. They cost a few € each.

Multimeter: A simple multimeter, that can measure voltage, current and resistance and in best case has a continuity check mode. This is a very important base tool for all electronics. I think most multimeters from 15€ up would be ok.

Pliers and Wire cutter: These are good for pressing and for cutting things. If you train a bit, you can even use the wire cutter for removing the isolation at the end of your wires. Technically a proper wire stripper is better, but I think using a wire cutter for the low budget start is totally ok. A wire cutter can go as cheap as 10-15€ for a decent one.

Soldering iron: Don't buy one of these soldering irons, that go directly into the mains. Buy a little soldering station with basic temperature control and integrated holder and a sponge for cleaning the tip. It should also have the possibility to change the tip (when you need a smaller/bigger tip or when your tip is no good anymore). A few years ago I got one of these for about 15€. Going a bit higher will benefit you with a better solder station.

Solder wire: You need to buy the actual solder. You should buy a spool of solder wire with integrated flux. Though most little spools have that. Depending on the exact solder wire it can be useful to also buy some flux (I'm currently using a flux pen), if the solder isn't flowing good enough.

Third hand with magnifying glass: When soldering it is sometimes helpful, when you can put a part into a clamp (like the third hand) and then use your hands for soldering iron and solder wire. The magnifying glass (which is also hold by the third hand) can help with small parts and inspection of your soldering work. It often costs only a few €, but getting up a bit can give you better durability and stability.

Perfboard: To build PCBs yourself you can most easily use perfboards. That are simple boards with solder pads for through-hole components. You can solder the components to the and then connect the pads via solder/wires. These are available with each pad not connected to anything else, or already connected like on a breadboard (I use these ones, like in this answer), or in stripes,... Building better PCBs would involve a more complicated process with chemicals or sending the PCB files to a manufacturer.

Heat shrink tubing/sleeves for wires and cables: To isolate wires, you might want to get correspondingly sizes heat shrink tube. They slide onto the to-isolate place and then get heated with a heat gun or a lighter. They shrink down and so enclose the part for isolation.

Oscilloscope: This is normally one of the most expensive tools. A decent oscilloscope can cost 250€ and up (into infinity). But you can sometimes get the big old oscilloscopes second hand (for example from ebay) as others upgrade to a digital oscilloscope. Or you can buy an USB oscilloscope, which works with your PC. I got one of these for about 50€. Or there are simple kits for standalone oscilloscopes (with limited capabilities) for 35€ and up. An oscilloscope is important for analyzing analog signals.

Logic Analyser: This is used to analyze digital signals. Standalone logic analyzers are expensive, but you can get a USB version for about 10€. The opensource software sigrok can then be used to interface the logic analyser. This tools is really really useful in relation to its low price. For example: You can use it as debug tools by setting pins inside your code at special places. That gives a better view on the temporal code flow than the typical Serial output.

Hot glue gun: Seems pretty basic, but I really often use my hot glue gun. You can fix things, protect them, build a supporting structure,... They only cost a few € plus a few for the glue sticks.

Scalpel and box cutter: Cutting things is also important and these two are good at it. They only cost a few € and have interchangeable blades. Especially a fresh scalpel blade can make the cutting of light materials really smooth.

That's about, what I can think of currently.

Thank you, you were the only one that if I explained what I wanted

I can't help with the whole laboratory, but I can suggest the free ArduinOscope mini-app to turn an Arduino UNO into an oscilloscope that uses your computer as the display. Here's the link to the Help topic that describes controls, features, and performance: https://www.daqarta.com/dw_rroo.htm.  This is a large macro script that comes with my Daqarta software https://www.daqarta.com. Please note that you don't have to purchase anything to use the DaquinOscope; a license is needed (after the trial period) only to use your sound card inputs, not the Arduino.  (You also don't need a license to use the sound card outputs, so you can use the free Daqarta Generator to create test signals.)
Enjoy!

thank you very much: 3


text:
DS3231 Clock project shows right date but wrong day
Heeya Guys!
Today I created a project with the help of instructables site. I followed the on screen steps and everything. Uploaded the sketch and it works like a charm, but there's one problem.
Everything works correctly but not the "Day", i.e as of today its Friday, 9 April 2021, the clock shows the correct time and date but it tells that today is "Tuesday" in place of Friday. I don't know why this is happening.
Any help would be appreciated :)
Here's the code that I'm using:
/*Arduino Clock by AnthoTRONICS
* Last edit: March 22,2019
*/
// Libraries you'll need (Same as the ones in the guide:
// TAKE NOTE OF THE VERSIONS!!!

// MD Parola 3.0.1: https://github.com/MajicDesigns/MD_Parola // click the link to download the library
// MD_MAX72XX 3.0.2: https://github.com/MajicDesigns/MD_MAX72XX //click the link to download the library
// DS3231 1.0.2: https://github.com/NorthernWidget/DS3231 // click the link to download

/*CODE:*/
// Header file includes
// These are for the matrix
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"

//These are for the clock
#include <DS3231.h>
#include <Wire.h>
DS3231 Clock;

bool Century=false;
bool h12;
bool PM;
byte  dd,mm,yyy;
uint16_t  h, m, s;

#define MAX_DEVICES 4 // Set the number of devices
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define CLK_PIN   13
#define DATA_PIN  11
#define CS_PIN    10

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE,CS_PIN, MAX_DEVICES);

#define SPEED_TIME 75 // speed of the transition
#define PAUSE_TIME  0

#define MAX_MESG  20

// Global variables
char szTime[9];    // mm:ss\0
char szMesg[MAX_MESG+1] = "";

uint8_t degC[] = { 6, 3, 3, 56, 68, 68, 68 }; // Deg C
uint8_t degF[] = { 6, 3, 3, 124, 20, 20, 4 }; // Deg F

char *mon2str(uint8_t mon, char *psz, uint8_t len)

// Get a label from PROGMEM into a char array
{
  static const __FlashStringHelper* str[] =
  {
    F("Jan"), F("Feb"), F("Mar"), F("Apr"),
    F("May"), F("Jun"), F("Jul"), F("Aug"),
    F("Sep"), F("Oct"), F("Nov"), F("Dec")
  };

  strncpy_P(psz, (const char PROGMEM *)str[mon-1], len);
  psz[len] = '\0';

  return(psz);
}

char *dow2str(uint8_t code, char *psz, uint8_t len)
{
  static const __FlashStringHelper*  str[] =
  {
  F("Sunday"), F("Monday"), F("Tuesday"),
  F("Wednesday"), F("Thursday"), F("Friday"),
  F("Saturday"), F("Sunday")
  };

  strncpy_P(psz, (const char PROGMEM *)str[code-1], len);
  psz[len] = '\0';

  return(psz);
}
// Time Setup: Code for reading clock time
void getTime(char *psz, bool f = true)
{
  s = Clock.getSecond();
  m = Clock.getMinute();
  h =Clock.getHour(h12,PM); //24hr Format
  sprintf(psz, "%02d%c%02d", h, (f ? ':' : ' '), m);
  //12hr Format
  //uncomment if you want the clock to be in 12hr Format
  /*if (Clock.getHour(h12,PM)>=13 || Clock.getHour(h12,PM)==0)
  {
    h = Clock.getHour(h12,PM) - 12;
  }
  else
  {
    h = Clock.getHour(h12,PM);
  }*/

}

void getDate(char *psz)
// Date Setup: Code for reading clock date
{
   char  szBuf[10];

   dd=Clock.getDate();
   mm=Clock.getMonth(Century); //12
   yyy=Clock.getYear();
   sprintf(psz, "%d %s %04d",dd , mon2str(mm, szBuf, sizeof(szBuf)-1),(yyy + 2000));
 //strcpy(szMesg, "29 Feb 2016");
}

void setup(void)
{
  P.begin(2);
  P.setInvert(false); //we don't want to invert anything so it is set to false
  Wire.begin();

  P.setZone(0,  MAX_DEVICES-4, MAX_DEVICES-1);

  P.setZone(1, MAX_DEVICES-4, MAX_DEVICES-1);
  P.displayZoneText(1, szTime, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);

  P.displayZoneText(0, szMesg, PA_CENTER, SPEED_TIME, 0,PA_PRINT , PA_NO_EFFECT);

  P.addChar('$', degC);
  P.addChar('&', degF);

}

void loop(void)
{
  static uint32_t lastTime = 0; // millis() memory
  static uint8_t  display = 0;  // current display mode
  static bool flasher = false;  // seconds passing flasher

  P.displayAnimate();

   if (P.getZoneStatus(0))
  {
    switch (display)
    {
      case 0:    // Temperature deg C
      P.setPause(0,1000);
      //P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_UP);
      P.setTextEffect(0, PA_MESH, PA_BLINDS);
      display++;
      dtostrf(Clock.getTemperature(), 3, 1, szMesg);
      strcat(szMesg, "$");
      //strcat(szMesg, "26.5$");

        break;

      case 1: // Temperature deg F
        //P.setTextEffect(0, PA_SCROLL_UP, PA_SCROLL_LEFT);
        P.setTextEffect(0, PA_OPENING, PA_GROW_DOWN);
        display++;
        dtostrf((1.8 *Clock.getTemperature() )+32, 3, 1, szMesg);
        strcat(szMesg, "&");

   // strcpy(szMesg, "71.6&");

        break;

      case 2: // Clock

     P.setFont(0, numeric7Seg);
     P.setTextEffect(0, PA_PRINT, PA_NO_EFFECT);
     //Sleep Mode
     //Uncomment to enable Sleep Mode and adjust the hours to your needs
     /*if (h==12 || h<8)//Time intervals (in this case, from 12AM to 8AM)
     {
      P.setIntensity(0); //Set display brightness to lowest setting
     }
     else
     {
      P.setIntensity(6); //Set display brightness to 6 (15 is the brighest)
     }*/
     P.setPause(0,0);

     if (millis() - lastTime >= 1000)
    {
    lastTime = millis();
    getTime(szMesg, flasher);
    flasher = !flasher;
    }
    if(s==00&& s<=30){
    display++;
    P.setTextEffect(0, PA_PRINT, PA_SCROLL_UP);
    }

    //  strcpy(szMesg, "36 % RH");

        break;

      case 3: // day of week

        P.setFont(0,nullptr);
        P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
        display++;
        dow2str(Clock.getDoW()+1, szMesg, MAX_MESG); // Added +1 to get correct DoW

       //dow2str(5, szMesg, MAX_MESG);
        break;
      default:  // Calendar

        P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
        display = 0;
        getDate(szMesg);
        break;
    }

    P.displayReset(0);
  }

}

If your problem isn't dependent on it, remove your display code and more people will be able to compile your example.

Did you set the correct day of the week? The clock can't work it out from the date, it needs to be told it.

Note that, unlike the DS3231 library, RTClib computes the day of the week from the other date fields.

put in a bunch of serial.print commands to determine what are the variable values at different points in the program flow

Re-read @Majenko's comment-- You need to set the correct DOW in the DS3231 when you set its time. The DS3231 does not reset the rolling DOW register when you reset the other registers.  If it is uninitialized, the results are indeterminate.  https://github.com/NorthernWidget/DS3231/blob/master/DS3231.cpp#L274

The library seems to be addressing device register 3.
According to the DS3231 datasheet this register has valid values 1-7, with 1 being Sunday.
You have:
dow2str(Clock.getDoW()+1, szMesg, MAX_MESG);

1-7 becomes 2-8.  And then, how dow2str:
strncpy_P(psz, (const char PROGMEM *)str[code-1], len);

2-8, become array indices 1-7.
Your array is:
  static const __FlashStringHelper*  str[] =
  {
  F("Sunday"), F("Monday"), F("Tuesday"),
  F("Wednesday"), F("Thursday"), F("Friday"),
  F("Saturday"), F("Sunday")
  };

The indices here start at 0, so everything is off-by-one.  But, I don't know how you get Tuesday out of Friday.  If you cut your code down to something smaller that is testable without the display code, just using Serial, you'll probably get better answers.

It is probably an initialization problem.  The DS3231 doesn't recompute the DOW when the other registers are set, so if the other registers are properly set but the register 3 DOW is wrong, it likely wasn't properly initialized with the rest.

I did this project and my weekday was off by 1, always a day earlier I fixed this by removing the Sunday at the beginning of the list and moving it to the end why you had two Sunday entries I do not know. That fixed my issue. I do not know why yours is showing Tuesday for Friday though.
char *dow2str(uint8_t code, char psz, uint8_t len)
{
static const __FlashStringHelper str[] =
{
F("Monday"), F("Tuesday"),
F("Wednesday"), F("Thursday"), F("Friday"),
F("Saturday"),F("Sunday")
}

Not an answer...


text:
Communication between two Arduinos using ENC28J60?
How can I connect and send data between two Arduinos using ENC28J60 ethernet adapters on both of them? Is there any guide or example code for me to take a look from or any library I can use to achieve this communication?
I have one Arduino connected to an ultrasound sensor and the other to a relay module so that one Arduino measures the distance between certain objects and send the distance to the other Arduino, which then processes it to check if it is within a certain limit. If not then it turns on the relay. I could have used two ESP32 with one in AP mode but the range is not enough and serial communication is not possible, as the cables are fragile and the distance is too large. Also I couldn't find another way of sending the data.
I'm open to any suggestion, even changing the method of communication. Or using of any other ethernet module.

You can use my EthernetENC library. See the examples of Arduino Ethernet library on how to use Ethernet libraries for Arduino.
EthernetClient object wraps a TCP socket. A normal TCP socket is connected to IP address and port. EthernetServer listens on a port. If server is contacted by a remote client socket, it creates a local socket connected with the remote client socket on a free port and returns a EthernetClient object wrapping the socket. Everything you write or print to a EthernetClient is send to that one remote socket.
If the client board creates a EthernetClient and connects it to IP address and port of the EthernetServer on your 'server' board, then you get there a EthernetClient from server.available() and this two EthernetClient objects are connected. What you write/print on one side you read only from the EthernetClient object on the other side.
client socket
   if (client.connect(serverIP, PORT)) {
     client.print("request\n");
     String response = client.readStringUntil('\n');
     Serial.println(response);
     client.stop();
   }

server side
   EthernetClient client = server.available();
   if (client && client.connected()) {
     String request = client.readStringUntil('\n');
     Serial.println(request);
     client.print("response\n");
     client.stop();
   }

You will need a crossover cable.