text:
Custom 328P-AU board not responding via ICSP
I created a custom PCB based on a 328P. The design is mainly based on the Arduino Nano schematic (3.0). The boards have arrived some days ago, and I can't get avrdude to recognize them via USBASP (or any other mean for that matter). When trying to program the board is powered via the ICSP connector. What I have tried so far:

only soldering the essential components: CAPs for 5V rail
soldering the Oscillator or leaving it off
on one board I even cut all lines except 5V, GND, RST and SPI.

Still the 328p won't respond, all I get is :
#avrdude -u -c usbasp -P COM1 -b 57600 -B 0.5 -p m8

 WARNING: Unable to detect MCU
 avrdude.exe: set SCK frequency to 1500000 Hz
 avrdude.exe: error: program enable: target doesn't answer. 1
 avrdude.exe: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.
 avrdude.exe done.  Thank you.

I will attach my schematics and my board design, I know it is not the cleanest for now... It is my first one and I am currently trying to clean it up/make it better. I also added 1k resistors in line to RX and TX, but they are not present in the board design for now.
I am thankful for any help and/or advice
I can provide the board design if needed:)

I can't see anything obvious in your design. Have you tested a board with a DMM to look for shorts and test continuity of relevant traces, and confirmed correct voltages?

yes I did, continuity is fine, resistance GND to 5V is about 15kOhms, so that may be fine too...There are no obvious shorts that I am aware of... Is it possible that the 328p's are all dead?

SCK frequency to 1500000 Hz  Whatever else you do, I'd lower that.  If you chip is fresh from the factory, that may even be the problem.

@timemage you are my hero!!! set it to 8k solved it:) thanks so much!!!!!

If you want you can post it as an answer.

Alright, well, I posted an answer so that it has one.

@timemage sorry saw it too late, thanks again !

So you had:

SCK frequency to 1500000

And I suggested lowering to the point where you:

set it to 8k solved it:)

Good deal.  The thing that you were likely running afoul of is the maximum ISP clock rate, which according to the datasheet for the ATMega328P (or practically any other AVR for that matter) is determined by some rules:

Low:> 2 CPU clock cycles for fck < 12MHz, 3 CPU clock cycles for fck ≥ 12MHz
High:> 2 CPU clock cycles for fck < 12MHz, 3 CPU clock cycles for fck ≥ 12MHz

So your maximum ISP clock rate is dependent on the chip's clock rate.  And is either at most a quarter of a sixth of that, depending on whether or not the chip operating below or above 12MHz.
Most ordering codes of AVRs of the type that do this kind of ISP programming ship from the factory at on the internal 8 MHz oscillator with the divide-by-8 fuse enabled; So they're at 1 MHz with a maximum ISP clock rate of 250 kHz.  Had you been working with a the typical Arduino arrangement when it had already been set up for and running with a 16 MHz clock, the 1.5 MHz ISP clock rate might have worked.  I'd have still slowed it down, since it will only be more likely to work when doing that.
Most programmers default to a low clock rate, closer to your 8k figure.  Usually, if people have a problem with hitting the maximum ISP clock rate, it's because they have a very low system clock, either using a watch crystal or fusing for the internal 128 kHz, or either in combination with the divide-by-8-fuse.  Often when trying to go too-fast, what's holding them up is crappy wiring.
When you're programming there's a limit to how useful it is to crank the clock rate up anyway, because eventually there's going to be a lot of hurry-up-and-wait while the chip flashes sectors and the timing of that isn't dependent on the clock rate.


text:
Parse the data incoming from the buffer of Serial.readBytes()
I want to parse the data of the incoming buffer from the serial read bytes, but I don't really know how to get the data out of the array and save it to different variables.
This is my code:
void setup() {
  Serial.begin(9600);
}

struct buf {
  byte FunctionCode;
  byte Length;
  byte Message;
  byte Checksum;
} data;

void loop() {
  int Length = Serial.available();
  byte Buffer[Length];
  byte IncomingData[Length];
  if (Length >= 0)
  {
    Serial.readBytes(Buffer, Length);
    data.FunctionCode = Buffer[0 - 1];
  }
}

What data? How is it formatted? Look at strtok() to do the heavy work for you.

@Majenko this is the incoming data: |61|191|16|0|61|191|100|23|0|0|0|0|0|0|131|2| (without the "|"), I can't use strtok because I'm not using string, they're just bytes

A string is just bytes...

@Majenko Yeah, btw I fixed everything just by using a for loop and some if statements

@alessandromrc, is it fair to say that you don't control for the format of the data being sent to you?

@timemagei I just send raw bytes to the Arduino

That sounds like "yes."  Part of what I'm getting at is you have could use any number of libraries for existing protocols.  Just from your FunctionCode mention alone, it's reminding me of MODBUS.

@timemage haha, It's a MODBUS emulation for real ... If I have to be really honest I'm not a fan of libraries, I prefer learning how to do everything by myself so I can understand how it really works and not by just hearing that by somebody else

source: Stack Exchange

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

sort: votes


text:
How to avoid stepper motor to revert its spin direction from code
I'm working with an Arduino UNO and a stepper motor NEMA 17. I would like to know how to avoid the stepper motor to revert its spin direction when I apply a load in the shaft. The motor works as I spect without any load, here is the code I'm using.
I think I'm missing something in the code, not in the connections.
// Define pin connections & motor's steps per revolution
const int dirPin = 2;
const int stepPin = 3;
const int stepsPerRevolution = 45;//115

void setup()
{
  // Declare pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
}
void loop()
{

if(true){
    // Set motor direction counterclockwise
  digitalWrite(dirPin, HIGH);

  // Spin motor quickly
  for(int x = 0; x < stepsPerRevolution; x++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(700); //670
    digitalWrite(stepPin, LOW);
    delayMicroseconds(700); //670
  }

  }
}

External voltage: 12 v 3A max
Motor's datasheet: 17HS4401S
Driver: DRV8825
Guide:https://lastminuteengineers.com/drv8825-stepper-motor-driver-arduino-tutorial/
Sketch

What's the load on the motor? Did you set the current limit? Have you checked the fault pin?

The load on the shaft is 0.3 kg cm, I’ve already set up the potentiometer (this is why the motor works fine) and since it’s not stop working the driver is always running ( no fault) it only reverse its spin direction

How is the load connected to the shaft? In other words are you sure it's the motor and not the mechanicals? Have you tried with something needing lower torque? I'd also double-check the coil wires--don't just rely on wire color.

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


text:
Why does this piece of code overflow at 255?
Im having a problem where i got unsinged long variable and i need to increment it in eeprom everytime setup starts and it overflows at 255 back to 0.
unsigned long NumberOfBoots = 0UL;
#define INFO_NUMBER_OF_BOOTS_ADDR 0
#define INFO_NUMBER_OF_BOOTS_LEN sizeof(NumberOfBoots)

// in setup
EEPROM.get(INFO_NUMBER_OF_BOOTS_ADDR, NumberOfBoots);
EEPROM.update(INFO_NUMBER_OF_BOOTS_ADDR, ++NumberOfBoots);

My guess is that its due to Update() fuction. Any ideas?

https://www.arduino.cc/en/Reference/EEPROMUpdate

And also https://www.arduino.cc/en/Reference/EEPROMPut

@DaveNewton
Thanks, so its actual limitation of Update function. I will use put. Thank you both


text:
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied Upload error:
I am using arduino-ide2.0.0-beta.7(CLI Version:0.18.3 alpha) on Manjaro Linux and I get this error when uploading sketch to my Arduino Micro:

avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied
Upload error: Error: 2 UNKNOWN: uploading error: uploading error: exit status 1

I checked other questions and tried:
sudo groupadd dialout
sudo gpasswd -a $USER dialout
sudo chmod a+rw /dev/ttyACM0
sudo usermod -a -G dialout $USER
sudo chown root:dialout -R /dev/
ls -l /dev/ttyACM0 #can see the root:dialout

But when I logout and get again after ls -l /dev/ttyACM0:

crw-rw-rw- 1 root uucp 166, 0  6月 13 17:06 /dev/ttyACM0

So I cannot upload the sketch. Note: I can upload sketches using sudo arduino-ide --no-sandbox , but I want to upload them from the user account.
What else can I try?
Thank you.

https://www.arduino.cc/en/Guide/Linux#please-read

@Juraj I had to run sudo usermod -a -G uucp $USER  instead of sudo usermod -a -G dialout $USER. Thanks.

Instead of:
sudo usermod -a -G dialout $USER

I had to run:
sudo usermod -a -G uucp $USER

Thanks to @Juraj I realized that. Thanks @Juraj.


text:
DC motor and buzzer blink without delay code
So I am trying to put together a code for 4dc motors, buzzer, ultrasonic and lcd to work together,. they will together make up a small car. when the distance to the ultrasonic is smaller than 10cm, the buzzer makes a random sound, and a funny face. Meanwhile the motors will stop for 2 seconds, goes back for 2 seconds and do a turning motion for 8 seconds. However. I do not want to use the delay function for the motors since it will cause the buzzer to sound too slowly. I know I need to do a blink without delay code, I am trying to implement this but am having trouble right now: the motors will stop when I put in the motor stop function, but it will not go backwards.. I know there are some timing issues but how can I fix this?
please see attached the code and wiring diagram.
Thank you sooo much !!!!
#include <LiquidCrystal.h>
#include <NewTone.h>

#include<AFMotor.h>
#define trigPin A1
#define echoPin A0

AF_DCMotor motor1(1,MOTOR34_1KHZ);
AF_DCMotor motor2(2,MOTOR34_1KHZ);
AF_DCMotor motor3(3,MOTOR34_1KHZ);
AF_DCMotor motor4(4,MOTOR34_1KHZ);

LiquidCrystal lcd(8, 9, 4, 7, 12, 13);

int buzzerPin = A2;
int notes[] = {262};
int dur = 100;
int maximum = 100;
long duration;
int distance;
int distanceUltra;
unsigned long previousBuzzerMillis = 0;
unsigned long previousDCStopMillis = 0;
unsigned long previousDCBackMillis = 0;
unsigned long currentMillis = 0;
const unsigned long DCStopInterval =2000;
const unsigned long DCBackInterval =2000;

byte a[]={
  B10001,
  B10001,
  B10101,
  B10101,
  B01010,
  B00000,
  B00000,
  B00000
  };

byte b[]={
  B00000,
  B00010,
  B00100,
  B01000,
  B01000,
  B01000,
  B01000,
  B01000
  };

byte c[]={
  B00000,
  B01000,
  B01000,
  B01000,
  B01000,
  B01000,
  B00100,
  B00010
  };

byte h[]={
  B00000,
  B01000,
  B00100,
  B00010,
  B00010,
  B00010,
  B00010,
  B00010
  };

void setup() {

  Serial.begin(9600);
  lcd.begin(16,2);
  pinMode (trigPin, OUTPUT);
  pinMode (echoPin, INPUT);
  lcd.createChar(0,a);
  lcd.createChar(1,b);
  lcd.createChar(2,h);
  lcd.createChar(3,c);

  pinMode(buzzerPin, OUTPUT);
  }

void loop() {

  currentMillis = millis();
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;

  Serial.print("distance:");
  Serial.println(distance);

  lcd.clear();
currentMillis = millis();

  if (distance <= 10){

    stopDCMotorStop();
    //stopDCMotorBack();

    }

  else{
    motor1.setSpeed(100);
    motor1.run(BACKWARD);
    motor2.setSpeed(100);
    motor2.run(BACKWARD);
    motor3.setSpeed(100);
    motor3.run(BACKWARD);
    motor4.setSpeed(100);
    motor4.run(BACKWARD);
      }

  if (distance <= 10){

    lcd.setCursor(5,1);   //set lcd faces
    lcd.write((char) 3);
    lcd.setCursor(5,0);
    lcd.write((char) 1);
    lcd.setCursor(9,1);
    lcd.write((char) 201);
    lcd.setCursor(9,0);
    lcd.write(2);
    lcd.setCursor(6,0);
    lcd.write("x");
    lcd.setCursor(8,0);
    lcd.write("x");
    lcd.setCursor(7,1);
    lcd.write("o");
    }

    if (distance <= 10){
      randSound(maximum);
    }

}

void randSound(int maximum){
  NewTone(buzzerPin, random(maximum, 10*maximum),dur);
  delay(maximum);
  noNewTone(buzzerPin);
}

void stopDCMotorStop(){

  if (currentMillis-previousDCStopMillis<= DCStopInterval) {
    motor1.setSpeed(0);
    motor1.run(RELEASE);
    motor2.setSpeed(0);
    motor2.run(RELEASE);
    motor3.setSpeed(0);
    motor3.run(RELEASE);
    motor4.setSpeed(0);
    motor4.run(RELEASE);
    previousDCStopMillis =currentMillis;
    }

  }

void stopDCMotorBack(){

  if (currentMillis-previousDCBackMillis<= DCBackInterval) {
    motor1.setSpeed(100);
    motor1.run(FORWARD);
    motor2.setSpeed(100);
    motor2.run(FORWARD);
    motor3.setSpeed(100);
    motor3.run(FORWARD);
    motor4.setSpeed(100);
    motor4.run(FORWARD);
    previousDCBackMillis =currentMillis;
    }
  }

use a state machine ... explore FSM ... https://duckduckgo.com/?q=fsm+arduino

use a variable to keep track of the state of the system ... when distance is below 10 cm, then set state to 1 ... states would be something like  0 no change ... 1 stop motors and go to state 2 ... 2 stay in state 2 for two seconds then go to state 3 ... 3 turn on reverse and go to state 4 ... 4 stay in state 4 for two seconds then go to state 5 ... 5 start turn and go to state 6 ... 6 stay in state 6 for eight seconds and go to state 7 ... etc. etc.


text:
invalid conversion from 'char' to 'const char*' [-fpermissive] on a string
I am compiling some code I didn't write, and it bombs out with the error message
invalid conversion from 'char' to 'const char*' [-fpermissive]

on the line
if (loginPassword == '\0') loginPassword = "";

I don't see why that line is any different than the previous strings, and the answers I can find all have to do with variables that start as char.
What is wrong with this code, and how do I fix it?
    void saveUnit(String tempUnit, String supportMode, String loginPassword, String minTemp, String maxTemp, String tempStep) {
      const size_t capacity = JSON_OBJECT_SIZE(6) + 200;
      DynamicJsonDocument doc(capacity);

      // if temp unit is empty, we use default celcius
      if (tempUnit == '\0') tempUnit = "cel";
      doc["unit_tempUnit"]   = tempUnit;

      // if minTemp is empty, we use default 16
      if (minTemp == '\0') minTemp = 16;
      doc["min_temp"]   = minTemp;

      // if maxTemp is empty, we use default 31
      if (maxTemp == '\0') maxTemp = 31;
      doc["max_temp"]   = maxTemp;

      // if tempStep is empty, we use default 1
      if (tempStep == '\0') tempStep = 1;
      doc["temp_step"] = tempStep;

      // if support mode is empty, we use default all mode
      if (supportMode == '\0') supportMode = "all";
      doc["support_mode"]   = supportMode;

      // if login password is empty, we use empty
      if (loginPassword == '\0') loginPassword = "";
      doc["login_password"]   = loginPassword;

      File configFile = SPIFFS.open(unit_conf, "w");
      if (!configFile) {
        // Serial.println(F("Failed to open config file for writing"));
      }

      serializeJson(doc, Serial);
      serializeJson(doc, configFile);

      configFile.close();
    }

I'm guessing this was copied out of a context where loginPassword was a pointer rather than String, where it probably should have really been compared with nullptr or 0 depending on the era of C++.

@timemage
https://github.com/gysmo38/mitsubishi2MQTT/blob/master/src/mitsubishi2mqtt/mitsubishi2mqtt.ino

Okay.  If that's the original context, I have no idea why it ever compiled.  You don't get this same error for supportMode and the others that follow this same pattern?

Correct, this is the first line that breaks. I can't figure why, when it should break before this.

It seems likely all that follow the pattern if (X == '\0') X = some_default; should have been written if (X == "")  ...  or maybe more efficiently if (X.length() == 0)  ..., but this is sort of nonsense for the loginPassword field. If it's already blank... it's blank.

Alright, well, if I run arduino-cli compile against an esp32:esp32:esp32 FQBN, with minimal scaffolding around your code, e.g. including ArduinoJson.h, SPIFFS.h, empty loop and setup, it compiles without error.  The esp32 core that happens to be on my machine is 1.0.4, probably old, but that's what I have.  ArduinoJson was version 6.18.0.

Same version of ArduinoJson, compiling against esp8266

Let us continue this discussion in chat.

Regardless of the findings below, you don't really want to compare a string object with a null-character this way (more on that below).  Really something like:  if (someArduinoStringObj.isEmpty()) { is a better idea, no matter what core you're on.
So for anyone that has landed here with this problem with code that had worked and no longer works, the answer is basically don't do that; probably shouldn't have been doing that in the first place.
If you're curious on what I found, there's material on that below.

So, I don't have a complete handle on this, but I do have something to report.   When we started going through this I didn't think there would be anything going on in the Arduino board support packages that would have any effect on this, but it turns out that's not the case.
We worked out that under ESP8266 Arduino core 3.0.0 the lines of the following form fail to compile and under version 2.7.4 the compile without error.  Here under 3.0.0 it was not picky about specifically loginPassword.
if (someArduinoStringObj == '\0') someArduinoStringObj = "some literal";

This can be abstracted to the somewhat nonsensical:
someArduinoStringObj == '\0';

Since that's the part makes the difference.  I really thought there was something more clever going on in the WString.h/WString.cpp code, an extra constructor or implicit conversion operator call prior to the code for the == operator.  There is an explicit constructor for String that takes a single char, but it's just that, it's explicit; it doesn't take part in evaluating the == expression above.  And there's no automatic conversion from String to const char *. It turns out that isn't anything clever going on in String class when it comes to this problem.  In fact you can boil this down to something similar so that the String class itself isn't actually involved at all, into:
void func(const char *) {}

void setup() {
  func('\0');
}

// ...

This will likewise pass compilation under 2.7.4 and fail with a similar error message under 3.0.0.  So, with String it is just trying to call the operator==(const char *), even though it's being given a char type.  Before getting into that, I tested a theory, which was to find out what happens if given == '\1'; or == 'X') etc, any non-zero value, because 0 has had an interesting relationship with pointers in C++ and C.  It makes more sense once you realize there's special going on in String.h.  We're basically talking about func('\0') vs func('\1') or func('X')  Well, under 2.7.4 these values fail where '\0' does not, but under 3.0.0 both fail.  So I got looking into the platform.txt file on both core versions, thinking maybe I'll spot a difference in compiler options.  E.g. it would make "sense" if 2.7.4 had -fpermissive where 3.0.0. didn't, but that's not the case.  The major difference is that 3.0.0 has -std=g++17 and 2.7.4 has -std=g++11.  Just for the hell of it I stole the command-line out of the verbose output compiling for the .ino.cpp file and replaced -std=g++17 with -std=g++11 and applied it to a cut-down file; didn't make any difference.  So, as far I tell there's some difference in default options specified between the two compiler versions in use in the two esp8266 package versions.
Constant expressions that evaluate to zero of int type (at least), will convert to null pointer constants.  I haven't been in the habit of using character-typed ('\0') zero valued constant expressions for null pointers, and I haven't dug through the various editions of the C++ standard to see what each one has to say about them; color me unsurprised either way.  But in any case, that's is basically what's happening here: The string object is being compared to a null pointer constant, at least when it compiles.  And if that makes you go WTF, well, me too.  If you follow this out, you ultimately you end up here:
unsigned char String::equals(const char *cstr) const {
    if (len() == 0)
        return (cstr == NULL || *cstr == 0);
    if (cstr == NULL)
        return buffer()[0] == 0;
    return strcmp(buffer(), cstr) == 0;
}

So, roughly speaking someArduinoString == '\0', where it will compile, is equivalent to someArduinoString == nullptr which is sort of the same effect as someArduinoString == "".  So, what you're seeing is not exactly an implicit form of someArduinoString == String('\0').
I can't picture wanting to say someArduinoString == '\0' over someArduinoString.isEmpty(), but in terms of why it doesn't work on 3.0.0, I'm still unsure.  I can tell you that it will if you plant -fpermissive into platform.txt, but that doesn't really explain it.  Sometime when I'm really bored I'll see what the language standard actually says and what versions of g++ did what under what options.
Even I worked that out my answer would still be: don't do that.


text:
Stop VSCode/Arduino add-in from sending reset signal in the event of compile errors
This is more of an annoyance, but if I edit a program with the serial monitor open, click "upload",  and the compile fails, the IDE switches to the serial monitor pane, opens the serial port which triggers a reset, and the last successfully uploaded version begins execution. This can be really annoying if you don't notice there were errors in the compile because VSCode automatically switches to the monitor pane and you waste time wondering why your code changes had no effect.
Is there any way to tell VSCode/Arduino add-in not to switch to the monitor pane in the event of a failed compile?

This doesn't happen for me; it compiles and ends with [Error] Uploading sketch 'blink.ino': Exit with code=1. You may need to provide more details.

@DaveNewton - you're right, of course. I looked more closely at what's going on and revised the question to reflect what I think it happening.

See https://github.com/microsoft/vscode-arduino/issues/1061; switching to the CLI tools might resolve this, but a (very) cursory inspection of the plugin was unenlightening at best. I'll look in to this because the Arduino output/console output thing has been a pain point for me as well sometimes.

@DaveNewton - look at Arduino.ts line 701. It appears that the CLI will behave the same way, as it also records if the Serial Monitor was open. The monitor is restored after compile at line 723 without checking if the compile was a success.

@DaveNewton - see my issue at the github repot


text:
RTC shield with LCD and Keypad
I am having issues with a code that I have been modifying.
I can change the TIME, and DATE from a keypad, and see the data on the serial monitor, but it is not recording on the SD Card. Anyone that could help me. Thank you.
#include <OneWire.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include "RTClib.h"

LiquidCrystal_I2C lcd(0x27,20,4)

RTC_DS3231 rtc;
DateTime   now;

const byte ROWS = 4;
 const byte COLS = 4;
 char keys[ROWS][COLS] = {
 {'1','2','3','A'},
 {'4','5','6','B'},
 {'7','8','9','C'},
 {'*','0','#','D'}
 };

 byte rowPINS[ROWS] = {10,9,8,7};
 byte colPINS[COLS] = {6,5,4,11};

 int i1,i2,i3,i4;
 char c1,c2,c3,c4;
 char keypressed;

 Keypad myKeypad = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);

#define DS18B20_PIN   A3

File dataLog;
boolean sd_ok = 0;

void setup()
{

  rtc.begin();          // initialize RTC chip

  lcd.init();     // initialize LCD module
  lcd.backlight();
  lcd.setCursor(0, 3);  // move cursor to column 0, row 3 (last row)
  lcd.print("Temp:");

// open serial communications and wait for port to open:
  Serial.begin(9600);
  Serial.print("Initializing SD card...");

// initialize the SD card
  if ( !SD.begin() )
    Serial.println(F("initialization failed!"));  // initialization error
else {   // initialization OK
    sd_ok = 1;
    Serial.println(F("initialization done."));
    if( SD.exists("Log.txt") == 0 )   // test if file with name 'Log.txt' already exists
    {  // create a text file named 'Log.txt'
      Serial.print("\r\nCreate 'Log.txt' file ... ");
      dataLog = SD.open("Log.txt", FILE_WRITE);   // create (&open) file Log.txt
      if(dataLog) {                               // if the file opened okay, write to it:
        Serial.println(F("OK"));
        // write some texts to 'Log.txt' file
        dataLog.println("    DATE    |    TIME  | TEMPERATURE");
        dataLog.println("(dd-mm-yyyy)|(hh:mm:ss)|");
        dataLog.close();   // close the file
      }
      else
        Serial.println(F("error creating file."));
    }
  }
   Serial.println(F("\r\n    DATE    |    TIME  | TEMPERATURE"));
   Serial.println(F("(dd-mm-yyyy)|(hh:mm:ss)|"));
}

// main loop
void loop()
{
  now = rtc.now();  // read current time and date from the RTC chip
  RTC_display();    // display time & calendar

  while(keypressed == NO_KEY){

  keypressed = myKeypad.getKey();

  now = rtc.now();  // read current time and date from the RTC chip
  RTC_display();    // display time & calendar

static byte p_second;
  if( (now.second()-1==0) ||  (now.second() % 5 == 0) && (p_second != now.second()) )
  {   // read & print temperature value from sensor every 10 seconds
    unsigned int ds18b20_temp;
    char buffer1[12], buffer2[26];
    bool sensor_ok = 0;

    p_second = now.second();
    if( ds18b20_read(&ds18b20_temp) )
    {
      sensor_ok = 1;
      if (ds18b20_temp & 0x8000)           // if temperature < 0
      {
        ds18b20_temp = ~ds18b20_temp + 1;  // change temperature value to positive form
        sprintf(buffer1, "-%02u.%04u%cC", (ds18b20_temp/16) % 100, (ds18b20_temp & 0x0F) * 625, 223);
      }
      else
      {      // otherwise (temperature >= 0)
        if (ds18b20_temp/16 >= 100)          // if temperature >= 100.0 °C
          sprintf(buffer1, "%03u.%04u%cC", ds18b20_temp/16, (ds18b20_temp & 0x0F) * 625, 223);
        else      // otherwise ( 0 <= temperature < 100.0)
          sprintf(buffer1, " %02u.%04u%cC", ds18b20_temp/16, (ds18b20_temp & 0x0F) * 625, 223);
      }
    }
    else
      sprintf(buffer1, "   ERROR  ");

    lcd.setCursor(5, 3);
    lcd.print(buffer1);

    sprintf( buffer2, " %02u-%02u-%04u | %02u:%02u:%02u | ", now.day(), now.month(), now.year(),
                      now.hour(), now.minute(), now.second() );
    if(sensor_ok) {
      buffer1[8] = 194;   // put degree symbol
      buffer1[9] = 176;
      buffer1[10] = 'C';  // put 'C' letter
      buffer1[11] = '\0'; // put string terminator
    }
    // print data on PC serial monitor
    Serial.print(buffer2);
    Serial.println(buffer1);
    // write data to SD card
    if(sd_ok)
    {  // if the SD card was successfully initialized
      // open Log.txt file with write permission
      dataLog = SD.open("Log.txt", FILE_WRITE);
      dataLog.print( buffer2 );
      dataLog.println( buffer1 );
      dataLog.close();   // close the file
    }

  }

  delay(100);   // wait 100ms

  }

if (keypressed == '*')
             {
              lcd.clear();
              lcd.print("     Setup");
             delay(1000);
              lcd.clear();
              lcd.print("Setup year");

             char keypressed2 = myKeypad.waitForKey();
                    if (keypressed2 != NO_KEY && keypressed2 !='*' && keypressed2 !='#' && keypressed2 !='A' && keypressed2 !='B' && keypressed2 !='C' && keypressed2 !='D' )
                      {
                       c1 = keypressed2;
                       lcd.setCursor(0, 1);
                       lcd.print(c1);
                       }
                 char      keypressed3 = myKeypad.waitForKey();
                    if (keypressed3 != NO_KEY && keypressed3 !='*' && keypressed3 !='#' && keypressed3 !='A' && keypressed3 !='B' && keypressed3 !='C' && keypressed3 !='D' )
                      {
                       c2 = keypressed3;
                       lcd.setCursor(1, 1);
                       lcd.print(c2);
                       }
                   char  keypressed4 = myKeypad.waitForKey();
                   if (keypressed4 != NO_KEY && keypressed4 !='*' && keypressed4 !='#' && keypressed4 !='A' && keypressed4 !='B' && keypressed4 !='C' && keypressed4 !='D' )
                      {
                       c3 = keypressed4;
                       lcd.setCursor(2, 1);
                       lcd.print(c3);
                       }
                   char   keypressed5 = myKeypad.waitForKey();
                   if (keypressed5 != NO_KEY && keypressed5 !='*' && keypressed5 !='#' && keypressed5 !='A' && keypressed5 !='B' && keypressed5 !='C' && keypressed5 !='D' )
                      {
                       c4 = keypressed5;
                       lcd.setCursor(3, 1);
                       lcd.print(c4);
                       }

                     i1=(c1-48)*1000;        //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
                     i2=(c2-48)*100;
                     i3=(c3-48)*10;
                     i4=c4-48;
                     int N_year=i1+i2+i3+i4;
                   delay(500);
                     lcd.clear();
                     lcd.print("Setup month");

////////////////////////////////////////////////////////////////
                     char keypressed6 = myKeypad.waitForKey();  // here all programs are stopped until you enter the four digits then it gets compared to the code above
                    if (keypressed6 != NO_KEY && keypressed6 !='*' && keypressed6 !='#' && keypressed6 !='A' && keypressed6 !='B' && keypressed6 !='C' && keypressed6 !='D' )
                      {
                       c1 = keypressed6;
                       lcd.setCursor(0, 1);
                       lcd.print(c1);
                       }
                    char   keypressed7 = myKeypad.waitForKey();
                    if (keypressed7 != NO_KEY && keypressed7 !='*' && keypressed7 !='#' && keypressed7 !='A' && keypressed7 !='B' && keypressed7 !='C' && keypressed7 !='D' )
                      {
                       c2 = keypressed7;
                       lcd.setCursor(1, 1);
                       lcd.print(c2);
                       }

                     i1=(c1-48)*10;
                     i2=c2-48;
                    int N_month=i1+i2;
                     delay(500);

                     lcd.clear();
                     lcd.print("Setup Day");

 ////////////////////////////////////////////////////////////////
                      char keypressed8 = myKeypad.waitForKey();  // here all programs are stopped until you enter the four digits then it gets compared to the code above
                    if (keypressed8 != NO_KEY && keypressed8 !='*' && keypressed8 !='#' && keypressed8 !='A' && keypressed8 !='B' && keypressed8 !='C' && keypressed8 !='D' )
                      {
                        c1 = keypressed8;
                       lcd.setCursor(0, 1);
                       lcd.print(c1);
                       }
                      char keypressed9 = myKeypad.waitForKey();
                    if (keypressed9 != NO_KEY && keypressed9 !='*' && keypressed9 !='#' && keypressed9 !='A' && keypressed9 !='B' && keypressed9 !='C' && keypressed9 !='D' )
                      {
                        c2 = keypressed9;
                       lcd.setCursor(1, 1);
                       lcd.print(c2);
                       }

                     i1=(c1-48)*10;
                     i2=c2-48;
                    int N_day=i1+i2;
                    delay(500);
                     lcd.clear();
                     lcd.print("Setup hour");

////////////////////////////////////////////////////////////////////////////////////:
                     char keypressed10 = myKeypad.waitForKey();  // here all programs are stopped until you enter the four digits then it gets compared to the code above
                    if (keypressed10 != NO_KEY && keypressed10 !='*' && keypressed10 !='#' && keypressed10 !='A' && keypressed10 !='B' && keypressed10 !='C' && keypressed10 !='D' )
                      {
                       c1 = keypressed10;
                       lcd.setCursor(0, 1);
                       lcd.print(c1);
                       }
                    char   keypressed11 = myKeypad.waitForKey();
                    if (keypressed11 != NO_KEY && keypressed11 !='*' && keypressed11 !='#' && keypressed11 !='A' && keypressed11 !='B' && keypressed11 !='C' && keypressed11 !='D' )
                      {
                        c2 = keypressed11;
                       lcd.setCursor(1, 1);
                       lcd.print(c2);
                       }

                     i1=(c1-48)*10;
                     i2=c2-48;
                    int N_hour=i1+i2;
                    delay(500);
                     lcd.clear();
                     lcd.print("Setup minutes");

////////////////////////////////////////////////////////////////////////////////////:
                    char keypressed12 = myKeypad.waitForKey();  // here all programs are stopped until you enter the four digits then it gets compared to the code above
                    if (keypressed12 != NO_KEY && keypressed12 !='*' && keypressed12 !='#' && keypressed12 !='A' && keypressed12 !='B' && keypressed12 !='C' && keypressed12 !='D' )
                      {
                        c1 = keypressed12;
                       lcd.setCursor(0, 1);
                       lcd.print(c1);
                       }
                   char    keypressed13 = myKeypad.waitForKey();
                    if (keypressed13 != NO_KEY && keypressed13 !='*' && keypressed13 !='#' && keypressed13 !='A' && keypressed13 !='B' && keypressed13 !='C' && keypressed13 !='D' )
                      {
                        c2 = keypressed13;
                       lcd.setCursor(1, 1);
                       lcd.print(c2);
                       }

                     i1=(c1-48)*10;
                     i2=c2-48;
                    int N_minutes=i1+i2;
                    delay(500);
                     lcd.clear();

                  rtc.adjust(DateTime(N_year, N_month, N_day, N_hour, N_minutes, 0));

                  RTC_display();
                  lcd.setCursor(0, 3);  // move cursor to column 0, row 3 (last row)
                  lcd.print("Temp:");

                  //myRTC.setDS1302Time(22, N_minutes, N_hour, 1, N_day, N_month, N_year); //once we're done setting the date and time we transfer to values to the RTC module
                                                                                //the 22 stands for seconds you can add a setup for it too if you want
                                                                                //the 1 stands for day of the week, as long I don't show it on the screen I don't change it
                    keypressed=NO_KEY; //the "*" key is stored in "keypressed" so I remove that value from it otherwise it will get me in the setup again
              }

}

//////////////////////////////////////// RTC functions ////////////////////////////////////////
void RTC_display()
{
  char _buffer[17];
  char dow_matrix[7][10] = {" SUNDAY  ", " MONDAY  ", " TUESDAY ", "WEDNESDAY",
                             "THURSDAY ", " FRIDAY  ", "SATURDAY "};
  lcd.setCursor(4, 0);
  lcd.print( dow_matrix[now.dayOfTheWeek()] );

  // print time
  sprintf( _buffer, "TIME: %02u:%02u:%02u", now.hour(), now.minute(), now.second() );
  lcd.setCursor(0, 1);
  lcd.print(_buffer);
  // print date
  sprintf( _buffer, "DATE: %02u-%02u-%04u", now.day(), now.month(), now.year() );
  lcd.setCursor(0, 2);
  lcd.print(_buffer);
}

////////////////////////////////////// end RTC functions //////////////////////////////////////

////////////////////////////////// DS18B20 sensor functions ///////////////////////////////////
bool ds18b20_start()
{
  bool ret = 0;
  digitalWrite(DS18B20_PIN, LOW);  // send reset pulse to the DS18B20 sensor
  pinMode(DS18B20_PIN, OUTPUT);
  delayMicroseconds(500);          // wait 500 us
  pinMode(DS18B20_PIN, INPUT);
  delayMicroseconds(100);          // wait to read the DS18B20 sensor response
  if (!digitalRead(DS18B20_PIN))
  {
    ret = 1;                  // DS18B20 sensor is present
    delayMicroseconds(400);   // wait 400 us
  }
  return(ret);
}

void ds18b20_write_bit(bool value)
{
  digitalWrite(DS18B20_PIN, LOW);
  pinMode(DS18B20_PIN, OUTPUT);
  delayMicroseconds(2);
  digitalWrite(DS18B20_PIN, value);
  delayMicroseconds(80);
  pinMode(DS18B20_PIN, INPUT);
  delayMicroseconds(2);
}

void ds18b20_write_byte(byte value)
{
  byte i;
  for(i = 0; i < 8; i++)
    ds18b20_write_bit(bitRead(value, i));
}

bool ds18b20_read_bit(void)
{
  bool value;
  digitalWrite(DS18B20_PIN, LOW);
  pinMode(DS18B20_PIN, OUTPUT);
  delayMicroseconds(2);
  pinMode(DS18B20_PIN, INPUT);
  delayMicroseconds(5);
  value = digitalRead(DS18B20_PIN);
  delayMicroseconds(100);
  return value;
}

byte ds18b20_read_byte(void)
{
  byte i, value;
  for(i = 0; i < 8; i++)
    bitWrite(value, i, ds18b20_read_bit());
  return value;
}

bool ds18b20_read(int *raw_temp_value)
{
  if (!ds18b20_start())  // send start pulse
    return(0);
  ds18b20_write_byte(0xCC);   // send skip ROM command
  ds18b20_write_byte(0x44);   // send start conversion command
  while(ds18b20_read_byte() == 0);  // wait for conversion complete
  if (!ds18b20_start())             // send start pulse
    return(0);                      // return 0 if error
  ds18b20_write_byte(0xCC);         // send skip ROM command
  ds18b20_write_byte(0xBE);         // send read command

  // read temperature LSB byte and store it on raw_temp_value LSB byte
  *raw_temp_value = ds18b20_read_byte();
  // read temperature MSB byte and store it on raw_temp_value MSB byte
  *raw_temp_value |= (unsigned int)(ds18b20_read_byte() << 8);

  return(1);  // OK --> return 1
}

why is the title of your post RTC shield with LCD and Keypad when the problem is with the SD card?

run an SD card read/write example sketch to confirm functionality


text:
Arduino Nano: MAX30102 and memory problems
We are making a simple pulse oximeter device with an Arduino Nano and a MAX30102 sensor.
The problem is the SpO2 reading and processing algorithm of the MAX30102 library literally does signal processing on the Arduino with large arrays of data and because of that, when you do BPM and SpO2, the 2kb memory of the Arduino is already full.
Can you guys give me some advice to overcome this problem?

If you mean large lookup tables / reference data, you should say, because that's definitely something worth knowing.  More details in any case.

Are you saying it doesn't work with just that library, or are you saying there are other libraries also that make it not work (like an OLED library)?

I meant the arrays that saves data. It takes 4 second of data and process it. That beginning data alone takes 400 bytes of 2k. And it hits %90 of 2kb at spo2,bpm and oled but i still need to add bluetooth.

Arduino UNO is not recommended for MAX30102 as it requires a lot of processing and RAM. Consider shifting to Arduino Mega or the ESP32.

In the question they acknowledge the library they're using uses a lot of ram. I think the question is how do they do it on their hardware despite that.  If it's fundamentally not doable in less ram, then explaining that might be useful.


text:
Encrypting the code using AES . ESP32
I am trying to figure it out. Why are my encryption and decryption not correct?
The used library for AES:
https://github.com/DanielVukelich/Arduino-AES
This is for testing encrypt and decrypt.
//https://www.hanewin.net/encrypt/aes/aes-test.htm
#include "Rij_Consts.h"
#include "Rijndael.h"

    void setup() {

      Serial.begin(115200);

      //mbedtls_aes_context aes;

      unsigned char iv[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

      //char * key = "abcdefghijklmnop";
      //const unsigned char key[16];
      const unsigned char key[16] = {0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA};
      //unsigned char key[16] = {0xFA,0xF9,0xF8,0xF7,0xF5,0xF4,0xF3,0xF2,0xF0,0xEF,0xEE,0xED,0xEB,0xEA,0xE9,0xE8};//กลับ

      //char *input = "Tech tutorials x";
     const unsigned char input[16] ={0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A};
      //unsigned char input[16] ={0x9A,0xE9,0x43,0x36,0x10,0x80,0x51,0x1D,0x33,0x9D,0xA6,0x78,0x22,0xAF,0x4B,0x01};//กลับ

      unsigned char output[16]; //6743C3D1519AB4F2CD9A78AB09A511BD ต้องได้ตามนี้

      printf("Testing ECB mode:\n");

      printf("Original Plaintext:\n");
      for(int i = 0; i < 16; i++){
        printf("%2.2X ", input[i]);
      }

      unsigned char keys[176];//for 128

      Schedule_Keys(AES_128, key, 16, keys);
      printf("\n\nKEYs:\n");
      for(int i = 0; i < 16; i++){
        printf("%2.2X ", keys[i]);
      }

      Encrypt(AES_128, input, 16, keys, output);

      printf("\n\nCiphertext:\n");
     for(int i = 0; i < 16; i++){
        char str[16];
        sprintf(str, "%2.2X ", output[i]);
        Serial.print(str);
     }

    Decrypt(AES_128, input, 16, keys, output);
    printf("\n\nCiphertext:\n");
    for(int i = 0; i < 16; i++){
        char str[16];
        sprintf(str, "%2.2X ", output[i]);
        Serial.print(str);
    }
    }

    void loop() {}

My output :

You can see my encryption and decryption not correct.
I tried to reconstruct the full code.
#include "Rij_Consts.h"
#include "Rijndael.h"

//https://www.hanewin.net/encrypt/aes/aes-test.htm   สำหรับเทสเทียบ

void setup() {
   Serial.begin(115200);
    unsigned char iv[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    const unsigned char key[16] = {0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0,0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA};
    const unsigned char plainText[16] ={0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33,0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A};
    unsigned char cipherText[16]; //6743C3D1519AB4F2CD9A78AB09A511BD Answer
    printf("Testing ECB mode:\n");

      printf("Original Plaintext:\n");
            for(int i = 0; i < 16; i++){
                  Serial.printf("%2.2X ", plainText[i]);
      }
        unsigned char keys[176];//for 128

        Schedule_Keys(AES_128, key, 16, keys);
            printf("\n\nKEYs:\n");
                for(int i = 0; i < 16; i++){
                    Serial.printf("%2.2X ", keys[i]);
      }

      Encrypt(AES_128, plainText, 16, keys,cipherText );
          Serial.printf("\n\nCiphertext:\n");
              for (int i = 0; i < 16; i++) {
                    Serial.printf("%2.2X ", cipherText[i]);
      }
      unsigned char decryptedText[16];

        Decrypt(AES_128,cipherText , 16, keys, decryptedText);

          Serial.printf("\n\ndecryptedText:\n");
              for (int i = 0; i < 16; i++) {
                    Serial.printf("%2.2X ", decryptedText[i]);
}
}

void loop() {}

Unfortunately I don’t have time to write a complete answer, but it looks like you’re attempting to  “decrypt” the (unencrypted) cleartext, not the ciphertext. The input of Decrypt should be the output of Encrypt.

Could you pls explain a little more about Encrypt and Decrypt? I'm kinda confused. But thanks for the comment

I want to Encrypt the code correctly first. but I don't know what to do. I keep missing and being wrong. My Encrypt is not correct that makes my Decrypt wrong too :<<<.

This is mainly a coding issue and not specific to Arduino. However, see my answer.

Could you pls send me the full code of ur answer to my Gmail? I want to compare to mine what did I do wrong. siripaiboon.J61@rsu.ac.th

With my answer you should be able to reconstruct the full code.

I'm outside, not back home yet. And appreciate you for helping me. You just came in the clutch.

I tried to reconstruct the code today. but My encrypt is still not correct at all. Do I really miss something in my new code. I did change as u said about Input, Output. My new code in the post.

Your reconstructed code as posted in your question runs exactly like it should on an ESP32 and also on an ESP8266. You seem to have renamed "Rijndael_Consts.h" to "Rij_Consts.h" so I had to fix that, but that could not have caused your issue. The output in my case was a correct Ciphertext and Decrypted text. How did you install the library?

Hmm, Interesting. I did not install it by myself. I got this library as WIN.RAR from my friend. I'll try to install it again. I'll let you know. After I install the new library.

I have a question. Why do my Encryption/Decryption not match the website we use to compare ? Even I use the same AES128-ECB :< https://www.hanewin.net/encrypt/aes/aes-test.htm

I don't know. You might try re-downloading and re-installing the library from Github.

Finally, I can encrypt the code correctly. Thanks for the advice. I tried re-installing from the library. It actually worked.

I tried to download the library from Github, but there is a file missing. Could you please provide another link?

@YathribElsiddig There are Rjindael.c, Rjindael.h, Rjindael_Consts. there is no file missing in the library. but you have to read  "README"  carefully first before you use his library with your project and I'm afraid that I don't have that link.  It was like 2 years ago

Maybe you try to redownload it like me. I had problem with download library before. you can see my post up there.

There are some issues with your code.
As mentioned in my comment, Decrypt () expects the Cipher Text as input and generates the Decrypted text as an output. However, in your code you're using the Plain text (which you confusingly named "input") as an input. The correct input should be your Cipher Text (which is the output from the Encrypt () function and which you called "output"). Please read the documentation of the AES library.
I suggest the following changes to your code to get it working:
Replace the part of your code, following Decrypt (...) until the end of setup() with the following code:
unsigned char decryptedText[16];
Decrypt(AES_128, output, 16, keys, decryptedText);

Serial.printf("\n\ndecryptedText:\n");
for (int i = 0; i < 16; i++) {
    Serial.printf("%2.2X ", decryptedText[i]);
}

I would also suggest you name your variables to avoid confusion, for example you could replace input[] with plainText[] and output[] with cipherText[]. Some of your Hex output code is also unnecessarily complex and could do with some restructuring.
I've compiled and run the above changes with your code on an ESP32 and it produces the expected Cipher text and correctly decrypts it. It produces the following output:
00:21:01.583 -> Testing ECB mode:
00:21:01.583 -> Original Plaintext:
00:21:01.630 -> 01 4B AF 22 78 A6 9D 33 1D 51 80 10 36 43 E9 9A
00:21:01.630 ->
00:21:01.630 -> KEYs:
00:21:01.630 -> E8 E9 EA EB ED EE EF F0 F2 F3 F4 F5 F7 F8 F9 FA
00:21:01.630 ->
00:21:01.630 -> Ciphertext:
00:21:01.630 -> 67 43 C3 D1 51 9A B4 F2 CD 9A 78 AB 09 A5 11 BD
00:21:01.630 ->
00:21:01.630 -> decryptedText:
00:21:01.630 -> 01 4B AF 22 78 A6 9D 33 1D 51 80 10 36 43 E9 9A

In your question you mention that the generated Cipher text is not as expected. I can't help you with that, as I can't reproduce it.


text:
Mesure sensor voltage by 328p and OP Amp in parallel
I am designing a circuit to measure the temperature via a thermistor via the ADC pin on a 328p and I am looking for some advice. As a failover I am also using an OP Amp as a comparator, to see whether the voltage exceeds a certain threshold. My question is the following. What can I do to protect the analog voltage line of the thermistor from interferences from the 328p? Can I connect the thermistor out directly to the 328p and to the MCU? My ideas are the following:

Using an in-line diode before the 328P adc pin, so that it can measure voltage but not interfere with it.
Using an OP Amp voltage follower to provide the voltage to the 328p pin

Is there a better way to do so? Are my possibilities feasible or are there any problems? What are the advantages and disadvantages of one or the other solution?
I am thankful for any help or advice.

simulate this circuit – Schematic created using CircuitLab

The ADC input is very high impedance, so unlikely to interfere with other measurements on the same pin.  You don't need either the diode or the separate op-amp.

@Boggyman however if the output impedance of Thermistor and R1 is around 50k, and you are measuring also something else, there will be much bigger crosstalk than if you have lower output impedance (recommendation from datasheet is up to 10k). However if he's measuring single slowly changing signal, then it won't be affecting it much

@KIIV I am quite new to this, R1 is 100k and I am measuring the voltage via 328p and the OpAmp. What exactly do you mean by crosstalk? Why should the impedance be lower? Hope I am understanding correctly that impedance is the measure of resistance in an AC circuit?

@jack There is a sampling capacitor (few pF), if you are charging it through 100k resistor, it'll take much more time to charge/discharge it from different voltage level, than if you have few kiloohms. And if it takes more than sampling time, you'll be measuring nonsenses. Mainly if you are measuring  something near 0V  and something with high impedance near 5V, it'll be really far from it's real value.

@KIIV thanks a lot for your explanation. I am sampling rather slowly on the 328p (one sample every 5s or so). Do you know where I can find the sampling rate for the OpAmp (LM324DT), I am that I have to ask, I am not even sure an OpAmp has a sampling rate

OpAmps doesn't have sampling rate, it has parameters like input impedance (but it's usually so big so it's usually ommited and defined by external resistors)

Thanks a lot for your help!


text:
nRF52 non-volatile storage/recall of a variable - is there a simple solution?
I have an Arduino program written for the nRF52 with which runs for a pre-set time-value (i.e. 2 minutes) before shuts off automatically.  The variable time-value can be changed via BLE-write by the user from an external device (i.e. from 2 mins to 5 mins). The problem that it defaults to the pre-set (2 mins) value once the program restarts.  How can I have the program "save" the last used time-value variable (i.e. 5 mins) for the next boot up/restart?
As I understand Nordic's nRF52 does NOT have an onboard EEPROM like AVRs.  I read about a Little File System by Adafruit that creates a sort of persistent storage space, but I hope there is something simpler.

Your options are the internal flash or an external EEPROM. If you're dealing with the internal flash then some sort of FS is likely the easiest choice. External EEPROM/FRAM can be as simple as an I2C chip and library. LFS doesn't create a "sort of persistent storage space", it's an FS abstration. There's also things like https://github.com/d00616/arduino-NVM.

https://www.arduino.cc/reference/en/libraries/arduino-nvm/

Thank you both.  I am digesting the linked information.  Will decide and try.  So far, I gathered that I need to be careful with not placing any write/erase related functions inside the "loop" as not to "wear out" the memory.

Reviewed the options. Just thinking out loud: Adadfuit already has some QSPI libraries and the chip on their boards. But requires 6 wires (normal SPI 4 wires). NVM is a no-external-parts solution, but does interfere with the nRF5's BLE softdevice stack requiring some fancy programming.   I am leaning towards EEPROM and FRAM for ease of addressing/programming, but both require some (small) external real estate.  However only a 1 or 2 wire I2C interface.

One other options is that upon bootup the sketch on my device would read user-selected values on the connected external BLE device app (phone, ectc) and use them as the variables values in the sketch:  for example time-delay selection for auto-off. .

The arduino-NVM library for nRF51 and nRF52 MCU has EEPROM object which emulates EEPROM in the internal flash memory of MCU.
The EEPROM object in arduino-NVM has the same functions as the EEPROM object in the Arduino EEPROM library for classic ATmega.


text:
State machine controlling dc motor/ buzzer/ lcd / ultrasonic
I ran into some problems here with programming. I am trying to put together a code for 4dc motors, buzzer, ultrasonic and lcd to work together,. they will together make up a small car. when the distance to the ultrasonic is smaller than 10cm, the buzzer makes a random sound, and a funny face. Meanwhile the motors will stop for 2 seconds, goes back for 2 seconds and do a turning motion for 8 seconds. However. I do not want to use the delay function for the motors since it will cause the buzzer to sound too slowly. I was directed from an earlier thread that I should use a state machine,but when I tried to put the motor controls in, my motors does not turn, can someone help me with spotting what is the problem here?
Thank you!
#define HALT_TIME 2000
#define BACK_TIME 2000
#define TURN_TIME 8000
#define trigPin A1
#define echoPin A0
#include <LiquidCrystal.h>
#include <NewTone.h>
#include<AFMotor.h>

long duration;
int distance;
int distanceUltra;
int maximum = 100;
int buzzerPin = A2;
int dur = 100;

LiquidCrystal lcd(8, 9, 4, 7, 12, 13);
AF_DCMotor motor1(1,MOTOR34_1KHZ);
AF_DCMotor motor2(2,MOTOR34_1KHZ);
AF_DCMotor motor3(3,MOTOR34_1KHZ);
AF_DCMotor motor4(4,MOTOR34_1KHZ);

enum ApplicationState {
  BeginDrive,
  Drive,
  BeginHalt,
  Halt,
  BeginBack,
  Back,
  BeginTurn,
  Turn
};

static enum ApplicationState currentApplicationState = BeginDrive;

static unsigned long t = 0;

static bool sensorTriggered() {

  if (distance <= 10){return true;}

  else {return false;}
}

static void funnyFace() {

    lcd.setCursor(6,0);
    lcd.write("x");
    lcd.setCursor(8,0);
    lcd.write("x");
    lcd.setCursor(7,1);
    lcd.write("o");
    randSound(maximum);//random sound for buzzer
}

static void beginDriveHandler() {
    Serial.println(currentApplicationState);

    motor1.setSpeed(100);
    motor1.run(BACKWARD);
    motor2.setSpeed(100);
    motor2.run(BACKWARD);
    motor3.setSpeed(100);
    motor3.run(BACKWARD);
    motor4.setSpeed(100);
    motor4.run(BACKWARD);
  currentApplicationState = Drive;

}

static void driveHandler() {

  if (sensorTriggered()) {
    Serial.println(currentApplicationState);
    t = millis();
    currentApplicationState = BeginHalt;
  }
}

static void beginHaltHandler() {
  Serial.println(currentApplicationState);
    motor1.setSpeed(0);
    motor1.run(RELEASE);
    motor2.setSpeed(0);
    motor2.run(RELEASE);
    motor3.setSpeed(0);
    motor3.run(RELEASE);
    motor4.setSpeed(0);
    motor4.run(RELEASE);

  funnyFace();
  currentApplicationState = Halt;
}

static void haltHandler() {

  if (millis() - t > HALT_TIME) {
    Serial.println(currentApplicationState);
    t = millis();
    currentApplicationState = BeginBack;
  }
}

static void beginBackHandler() {
Serial.println(currentApplicationState);
    motor1.setSpeed(100);
    motor1.run(FORWARD);
    motor2.setSpeed(100);
    motor2.run(FORWARD);
    motor3.setSpeed(100);
    motor3.run(FORWARD);
    motor4.setSpeed(100);
    motor4.run(FORWARD);
  currentApplicationState = Back;
}

static void backHandler() {

  if (millis() - t > BACK_TIME) {
    Serial.println(currentApplicationState);
    t = millis();
    currentApplicationState = BeginTurn;
  }
}

static void beginTurnHandler() {
Serial.println(currentApplicationState);
    motor1.setSpeed(100);
    motor1.run(FORWARD);
    motor2.setSpeed(100);
    motor2.run(FORWARD);
    motor3.setSpeed(100);
    motor3.run(BACKWARD);
    motor4.setSpeed(100);
    motor4.run(BACKWARD);
  currentApplicationState = Turn;
}

static void turnHandler() {

  if (millis() - t > TURN_TIME) {
    Serial.println(currentApplicationState);
    currentApplicationState = BeginDrive;
  }
}

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

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  //Serial.println(sensorTriggered());
  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;
  switch (currentApplicationState) {

    case BeginDrive:
    beginDriveHandler();
    break;

    case Drive:
    driveHandler();
    break;

    case BeginHalt:
    beginHaltHandler();
    break;

    case Halt:
    haltHandler();
    break;

    case BeginBack:
    beginBackHandler();
    break;

    case Back:
    backHandler();
    break;

    case BeginTurn:
    beginTurnHandler();
    break;

    case Turn:
    turnHandler();
    break;
  }

  //Serial.println(currentApplicationState);
}

void randSound(int maximum){
  NewTone(buzzerPin, random(maximum, 10*maximum),dur);
  delay(maximum);
  noNewTone(buzzerPin);
}

If you are really using a 9 volt battery you are very likely under powering your project.  While the voltage may work, the amount of current such a battery can produce is likely way below what your project needs to operate as expected.

Those little yellow gearmotors are typically around 200mA each with no load. You'd be far better off powering at least the motors w/ a bank of AAs.

You need to set t to millis() before reaching the handler with the if millis statement, so in the Begin... Handlers. Otherwise most likely t has such an old value, that the state will change immediately.

start motors and store the value of millis() for the 2 second timer in beginDriveHandler ... watch the time and sensor in driveHandler


text:
My Arduino don't show port but is working
I have some problem with Arduino uno and asked here, so I have tried to work by my STM32F103C8 as alternative board, and solved my problem by this question:
Arduino Port Not detected and can not run it as root
But now I as seeing that the Arduino port again is not acceptable but I can upload the codes into the STM32F103C8 board, so I asked why this happen ?

Note : I have seen this post which the STm32F103C8 board have some port on Arduino IDE (as you can see below ):

Update:
I have seen The below post about the same problem as you can see below:
Can't open serial monitor using ST Link and STM32F103C8
But, based of the last part of above post,which is shown below,
I don't get have could i have enable the serial port connection for the STM32f103C8 Board:

I did everything as it was described in tutorial, flashing bootloader
was succes, everything went ok, but windows still can't recognize it.
I am thinking that maybe it is problem with that resistor and maybe i
have to mod it... I think I will be sticking to ST-Link for uploading
codes and USB-UART for serial. But thanks for help
And one more question, can you tell me how to reset my Blue Pill to
factory bootloader (how to delete stm32 bootloader that I installed)

Thank.

it doesn't work. only the tool reports a wrong result

Is there a default that it tries to transmit the sketch to if no ports are selected?

The STM32F103C8 has a native USB interface. You will only ever see a CDC/ACM (USB UART emulation) interface if you actively run code that implements a CDC/ACM interface.
The bootloader is separate to your code. I don't know what protocol the bootloader for your board uses, but it may not even have a CDC/ACM interface to it.
In short: it doesn't have a port because you haven't programmed it to have a port, and the code uploading doesn't use a port, so doesn't care.

Thanks, but was is the means of /dev/2 on the Arduino IDE result which shown here?!

It'll be something specific to dfu-util. Btw, dfu is a custom protocol that has no serial or anything like it.

So You are saying, For enabling the port option in Arduino IDE, I must burn some boatloader to the STM32f103c8 board by Arduino IDE or other software?

No, you just write a sketch that uses the usb serial.


text:
Is it possible to read multiple buttons with the CD74HC4067?
I am working on a project with a claw machine. I am working on this chip (CD4067BE which is equivalent to the CD74HC4067) and I was wondering: can I read more than one button with the CD4067? I tried the following code, and it works great, but when I want to push two buttons, it will not read both of them as zero. Why am I using a chip with the buttons? It was to reduce I/O pins on my PCB for the claw machine. Yes, I could use a matrix, but I want control over my components, whether to turn it on or off. Also, the CD4067 includes all my buttons. I have thirteen buttons. (13 buttons). By the way, this chip is a multiplexer/demultiplexer. I am using this chip as a multiplexer. Oh, and also, I have an Arduino Mega 2560 rev3. I have followed the instructions of this question, but this doesn't answer if the chip can read more than button at one time. Thanks,
Austin
//Mux control pins
int s0 = 5;
int s1 = 4;
int s2 = 3;
int s3 = 2;

//Mux in "SIG" pin
int SIG_pin = 6;

void setup() {

  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);

  pinMode(SIG_pin, INPUT_PULLUP);

  Serial.begin(9600);
}

void loop() {

  //Loop through and read all 16 values
  for (int i = 0; i < 16; i ++) {
    Serial.print("Value at channel ");
    Serial.print(i);
    Serial.print("is : ");
    Serial.println(readMux(i));
    delay(1000);
  }
}

int readMux(int channel) {
  int controlPin[] =       {s0, s1, s2, s3};
  int muxChannel[16][4] = { {0, 0, 0, 0},
                            {1, 0, 0, 0},
                            {0, 1, 0, 0},
                            {1, 1, 0, 0},
                            {0, 0, 1, 0},
                            {1, 0, 1, 0},
                            {0, 1, 1, 0},
                            {1, 1, 1, 0},
                            {0, 0, 0, 1},
                            {1, 0, 0, 1},
                            {0, 1, 0, 1},
                            {1, 1, 0, 1},
                            {0, 0, 1, 1},
                            {1, 0, 1, 1},
                            {0, 1, 1, 1},
                            {1, 1, 1, 1}
                          };
  //loop through the 4 sig
  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }
  //read the value at the SIG pin
  int val = digitalRead(SIG_pin); //return the value
  return val;
}

There is no reason why it can't be used as you want. You're not reading two buttons at once, you're only ever reading one button, the other buttons are ignored. However you should have a pullup on every button, not just the Arduino's IO pin.

Why do the buttons need a pullup resistor? How do I go about reading more than one button at one time?

The buttons that aren't being read at any one moment will be floating. You need pullups. You don't read more than one button at one time. You only ever read one button. There is only ever one button - the button that is currently selected. All other buttons do not exist.

If you cycle through the mux's inputs it'll read whatever is there--you're only reading one button at a time, but if it's quick enough, it won't matter. You'll sometimes see circuits w/ a mux that include an aggregated interrupt indicating the processor should read from the mux.

Is it possible to use LEDs instead of pullup resistors? I read about that on this tutorial: https://www.baldengineer.com/arduino-keyboard-matrix-tutorial.html

So, this "floating", is it the same as "ghosting" from that tutorial?

floating refers to an input that has a high impedance (resistance) to both ground and supply ... ambient electric charges can randomly push the input to one of the two states ........ ghosting happens in some matrix keypads, where a non-pressed key is detected as being pressed because of two, or more, other keys are pressed ... this is the result of the design of the keypad

I'm not sure if it's an issue to have floating pins on Analog MUX. Maybe some day I'll test if there is higher current draw if left unconnected, but it's not switching anything between two states (and in CMOS switching needs current), so one pull up on the muxed side might be enough. Maybe with bigger line capacitance it might get some false presses when switched to level near gnd?

Yeah, I am not so sure what floating means and I still don't get the difference.

Okay, so, I'll put the pullup resistors on. But, what I want to know is how do I read multiple buttons on the chip all at once?

You don't--you read them one at a time; that's what thismux does--turns n signals into one signal, which you select with S0-S3. Again--if you read them sequentially, with little or no delay, it's unlikely to matter--computers fast, humans slow.

Okay, so, maybe I should switch to the matrix, considering that when I read the data, even fast, it won't work for what I am doing. So, basically, I am trying to use a joystick and some other buttons to run with stepper motors (to control them) on my claw machine. But, the problem is that when I would use a button, it would scan it individually. So, the buttons would not be "smooth," the stepper would have to wait until it gets to a certain channel. It would be a bumpy ride, in other words.

I think you're over-estimating human perceptive ability, or under-estimating computer speed.

OT: Your function readMux() will be more efficient and faster if you define the constant arrays as such: static const int controlPin[] = /*...*/; and static const int muxChannel[] = /*...*/;. Currently these variables are allocated on the stack and initialized each time you call the function.

I think that you are misunderstanding the concept of a multiplexer. Its purpose is to allow multiple signals to share one signal. Therefore you can only read one at a time. If you want to read them simultaneously, you will need an input/output expander. This will allow you to sample all the signals simultaneously on command, then send the data either serially or parallely to the MCU.

Yeah, but I was just experimenting with this new chip based on that question from Electrical Engineering. I think a matrix will work well for my new PCB design.

Although, I do want to thank everyone for helping me. I know understand that the concept of the mux is to read with a single output/input. So, it HAS to read it one at a time, because I don't want extra hardware. It's been fun. I will post the link to the tutorial for my claw machine on the Arduino Forum at arduino.cc in the upcoming future. Thank you very much!

An alternative way to write to the 4-bit MUX select pins is to use shifting and masking, something like this:
// MUX control pins
byte s0 = 2;
byte s1 = 3;
byte s2 = 4;
byte s3 = 5;
byte controlPin[] = { s0, s1, s2, s3 };

. . .

byte readMux(byte channel)
{
  // Loop through the 4 signals
  for (byte b = 0; b < 4; b++, channel >>= 1)
  {
    digitalWrite(controlPin[b], channel & 1);
  }
  // Read and return the value at the SIG pin
  return digitalRead(SIG_pin);
}


text:
Adafruit Featherwing Latching Relay lamp switch
I am brand new to Arduino. So I apologize in advance if I have missed the information I am looking for. I have looked for hours and cannot find any help with a Adafruit Featherwing Latching Relay(#2923 on Adafruit). This is the one that has 2 set pins "Set" & "Unset". I would love to use a Wemos d1 mini to trigger this relay. But I cannot find any sketchs or documentation on how to get started.
Ideally the setup would have a push button to toggle between states as well as the basic esp8266 web page to toggle state as well.
I am just trying to turn off/on some LEDs. And want to run the switch via this setup.
Thanks
E
Well I am further along. I was able to get most of this working but now the CSS i am using is causing headaches. The code below errors on "page =
Simple NodeMCU Web Server

    <button class="button">ON</button>         <button>OFF</button>
";
I get the error 'inconsistent user-defined literal suffixes 'LEDOn' and 'button' in string literal'
Any help would most appreciated. This line is the only one failing in my sketch

Please ask a new question for a new question rather than globbing it onto an existing one, particularly when it regards a completely separate topic. If you're having code issues including the code would be... helpful.

I will add the final code here. It took me weeks to find a starting place and many hours of trial and error to sort it all out. With help I was able to get a stable working switch.
This code was written for a Wemos D1 Mini coupled to a Adafruit Featherwing Latching relay. Since it has Set and Unset pins coding this was struggle for me. The Set/Unset pins only require a pulse to trigger them then they stay 'Latched' in state. even if power is lost. I found the base code here and it took a bit of tweaking to get it to work.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

// Replace with your network credentials
const char* ssid = "SSID";
const char* password = "PASSWORD";

ESP8266WebServer server(80);   //instantiate server at port 80 (http port)

String page = "";
int LEDUnsetPin = D1;
int LEDSetPin = D2;
void setup(void){
 //the HTML of the web page
 //don’t forget you need estapes (") around the quotes
 page = "
Kitchen LEDs

    <button class=\"button\">ON</button>         <button>OFF</button>
";
 //make the LED pins output and initially turned off
 pinMode(LEDUnsetPin, OUTPUT);
 digitalWrite(LEDUnsetPin, LOW);
 pinMode(LEDSetPin, OUTPUT);
 digitalWrite(LEDSetPin, LOW);

 delay(1000);
 Serial.begin(115200);
 WiFi.begin(ssid, password); //begin WiFi connection
 Serial.println("");

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

 server.on("/", [](){
   server.send(200, "text/html", page);
 });

 //turn on the on pin and turn off the off pin
 server.on("/LEDOn", [](){
   server.send(200, "text/html", page);
   digitalWrite(LEDSetPin, HIGH);
   delay(10);
   digitalWrite(LEDSetPin, LOW);
   delay(10);
 });

 //turn off the on pin and turn on the off pin
 server.on("/LEDOff", [](){
   server.send(200, "text/html", page);
   digitalWrite(LEDUnsetPin, HIGH);
   delay(10);
   digitalWrite(LEDUnsetPin, LOW);
   delay(10);
 });
 server.begin();
 Serial.println("Web server started!");
}

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

That board is specifically designed for the Feather ecosystem, so you'd need to provide the relevant connections, looks like 3.3V and GND, and the two input signals (also 3.3V, I assume). Nutshell: you can ignore almost every single connector on the board except for 3.3V, GND, SET, and UNSET.
Any D1 (or Arduino in general) tutorial that discusses how to set an output pin value is fine--you'd need them to be LOW by default and bring the relevant one HIGH for 10ms (delay is fine here) to set the new state.
Any switch input tutorial should be fine for learning how to read a switch, and there are multiple tutorials regarding setting up a simple web app that interacts with 8266 IO. Note that you'll want to keep track of the current state, though, and probably update the web app with the current state if it's changed via the button.
All this said: "just trying to turn off/on some LEDs" is broad. A relay may not be necessary; is there an explicit need for a latching relay?

Dave - This pretty much what I am after. There is no explicit need really just a learning exercise. Really finding an answer to a question no one asked ;o) - If anyone wants to provide code.... that would be awesome but I'm not greedy and can dig it up myself. Thanks


text:
Problem sending data via Bluetooth
I have an HM-11 BT module that I am configuring as a Master/Central and attempting to connecting to a SH-M08 BT slave module.
I can connect to the slave successfully but I cant send data.
I found this code on line. After configuring the HM-11, scanning and printing the found BT modules to serial, it reads commands from the serial port.
From the serial monitor I can send AT+CON[ADDR] and get back OK+CONNA and OK+CONN which indicates that connection was successful.
When I attempt to send anything via the serial connection it does not get received by the slave BT. I am able to used an app on my phone to send data to the slave BT.
This is the code.
SoftwareSerial BTserial(2, 3); // RX, TX

#define baud 9600

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(baud);
  BTserial.begin(baud);

  at("AT"); // check if working, always returns OK
  at("AT+RENEW"); // select master = central
  at("AT+ROLE1"); // select master = centra
  at("AT+RESET"); // actually more a restart than a reset .. needed after ROLE
  at("AT+SHOW1"); // include Bluetooth name in response
  at("AT+SCAN5"); // set discobery time to 5 seconds
  at("AT+IMME1"); // "work immediately", not sure what this does
  //at("AT+FILT0"); // show all BLE devices, not only HM ones
  delay(1000); // wait a bit, NECESSARY!!
  BTserial.print("AT+DISC?"); // here comes the magic
 while(!BTserial.find("OK+DISCS")) Serial.print(".");
   Serial.println("OK+DISCS");
}

void at(char* cmd) {
  BTserial.write(cmd);
  Serial.print(cmd);
  while(!BTserial.find("OK")) Serial.print(".");
  while (BTserial.available()) Serial.write(BTserial.read());
  Serial.println(" .. OK");
}

void loop() // run over and over
{
  if (BTserial.available())
    Serial.write(BTserial.read());
  if (Serial.available())
    BTserial.write(Serial.read());
}


text:
NodeMCU wont connect to Blynk
My NodeMCU wont connect to Blynk with my code but works fine with example code and same auth token and WiFi info. Cant figure out why its not working. Must be something in my code interfering with it (Or something stupid I'm missing). Any ideas? Thanks!
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "AUTH";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "SSID";
char pass[] = "PASSWD";

const int analogPin = A0;

const int muxA = 9;// MUX pin A
const int muxB = 10;//MUX pin B
const int muxC = 16;//MUX pin C

const int outputPin0 = 4;// output pin 0
const int outputPin1 = 5;// output pin 1
const int outputPin2 = 12;//Output pin 2
const int outputPin3 = 13;//output pin 3
const int outputPin4 = 14;//output pin 4

int startWatering0 = 1023;//start watering value 0
int startWatering1 = 1023;//start watering value 1
int startWatering2 = 1023;//start watering value 2
int startWatering3 = 1023;//start watering value 3
int startWatering4 = 1023;//start watering value 4

int currentMoisture0 = 0;//current moisture value 0
int currentMoisture1 = 0;//current moisture value 1
int currentMoisture2 = 0;//current moisture value 2
int currentMoisture3 = 0;//current mousture value 3
int currentMoisture4 = 0;//current moisture value 4

int wateringTime0 = 0;//watering time 0
int wateringTime1 = 0;//watering time 1
int wateringTime2 = 0;//watering time 2
int wateringTime3 = 0;//watering time 3
int wateringTime4 = 0;//watering time 4

bool isWatering0 = false;//is 0 currently watering
bool isWatering1 = false;//is 1 currently watering
bool isWatering2 = false;//is 2 currently watering
bool isWatering3 = false;//is 3 currently watering
bool isWatering4 = false;//is 4 currently watering

long wateringStart0 = 0;//watering 0 start value
long wateringStart1 = 0;//watering 1 start value
long wateringStart2 = 0;//watering 2 start value
long wateringStart3 = 0;//watering 3 start value
long wateringStart4 = 0;//watering 4 start value

BlynkTimer timer;

void setup()
{
  //initialize outputs
  pinMode(muxA, OUTPUT);
  pinMode(muxB, OUTPUT);
  pinMode(muxC, OUTPUT);

  pinMode(outputPin0, OUTPUT);
  pinMode(outputPin1, OUTPUT);
  pinMode(outputPin2, OUTPUT);
  pinMode(outputPin3, OUTPUT);
  pinMode(outputPin4, OUTPUT);

  Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);

  timer.setInterval(1000L, checkSensors);
}

void checkSensors()
{
  //check sensors here
  setMux0();
  currentMoisture0 = analogRead(analogPin);
  setMux1();
  currentMoisture1 = analogRead(analogPin);
  setMux2();
  currentMoisture2 = analogRead(analogPin);
  setMux3();
  currentMoisture3 = analogRead(analogPin);
  setMux4();
  currentMoisture4 = analogRead(analogPin);
  setMux5();
  setMux6();
  setMux7();

  Blynk.virtualWrite(V11, currentMoisture0);
  Blynk.virtualWrite(V12, currentMoisture1);
  Blynk.virtualWrite(V13, currentMoisture2);
  Blynk.virtualWrite(V14, currentMoisture3);
  Blynk.virtualWrite(V15, currentMoisture4);

  //starts watering if soil is drier than set value, and if it is not already watering
  if(currentMoisture0 >= startWatering0 && isWatering0 == false)
  {
    isWatering0 = true;
    digitalWrite(outputPin0, HIGH);
    wateringStart0 = millis();
  }

  if(currentMoisture1 >= startWatering1 && isWatering1 == false)
  {
    isWatering1 = true;
    digitalWrite(outputPin1, HIGH);
    wateringStart1 = millis();
  }

  if(currentMoisture2 >= startWatering2 && isWatering3 == false)
  {
    isWatering2 = true;
    digitalWrite(outputPin2, HIGH);
    wateringStart2 = millis();
  }

  if(currentMoisture3 >= startWatering3 && isWatering3 == false)
  {
    isWatering3 = true;
    digitalWrite(outputPin3, HIGH);
    wateringStart3 = millis();
  }

  if(currentMoisture4 >= startWatering4 && isWatering4 == false)
  {
    isWatering4 = true;
    digitalWrite(outputPin4, HIGH);
    wateringStart4 = millis();
  }

///////////////////////////////////////////////////////////////////////////////////
  //stops watering if it is currently watering, and it has been watering for longer than the set time
  if(millis() >= wateringStart0 + (wateringTime0 * 60000 ) && isWatering0 == true)
  {
    isWatering0 = false;
    digitalWrite(outputPin0, LOW);
  }

  if(millis() >= wateringStart1 + (wateringTime1 * 60000 ) && isWatering1 == true)
  {
    isWatering1 = false;
    digitalWrite(outputPin1, LOW);
  }

  if(millis() >= wateringStart2 + (wateringTime2 * 60000 ) && isWatering2 == true)
  {
    isWatering2 = false;
    digitalWrite(outputPin2, LOW);
  }

  if(millis() >= wateringStart3 + (wateringTime3 * 60000 ) && isWatering3 == true)
  {
    isWatering3 = false;
    digitalWrite(outputPin3, LOW);
  }

  if(millis() >= wateringStart4 + (wateringTime4 * 60000 ) && isWatering4 == true)
  {
    isWatering4 = false;
    digitalWrite(outputPin4, LOW);
  }
}

void setMux0()//sets mux to pin 0
{
  digitalWrite(muxA, LOW);
  digitalWrite(muxB, LOW);
  digitalWrite(muxC, LOW);
}

void setMux1()//sets mux to pin 1
{
  digitalWrite(muxA, HIGH);
  digitalWrite(muxB, LOW);
  digitalWrite(muxC, LOW);
}

void setMux2()//sets mux to pin 2
{
  digitalWrite(muxA, LOW);
  digitalWrite(muxB, HIGH);
  digitalWrite(muxC, LOW);
}

void setMux3()//sets mux to pin 3
{
  digitalWrite(muxA, HIGH);
  digitalWrite(muxB, HIGH);
  digitalWrite(muxC, LOW);
}

void setMux4()//sets mux to pin 4
{
  digitalWrite(muxA, LOW);
  digitalWrite(muxB, LOW);
  digitalWrite(muxC, HIGH);
}

void setMux5()//sets mux to pin 5
{
  digitalWrite(muxA, HIGH);
  digitalWrite(muxB, LOW);
  digitalWrite(muxC, HIGH);
}

void setMux6()//sets mux to pin 6
{
  digitalWrite(muxA, LOW);
  digitalWrite(muxB, HIGH);
  digitalWrite(muxC, HIGH);
}

void setMux7()//sets mux to pin 7
{
  digitalWrite(muxA, HIGH);
  digitalWrite(muxB, HIGH);
  digitalWrite(muxC, HIGH);
}

//sets values when they are changed in app

//start watering values

BLYNK_WRITE(V1)
{
  int startWatering0 = param.asInt();
}

BLYNK_WRITE(V2)
{
  int startWatering1 = param.asInt();
}

BLYNK_WRITE(V3)
{
  int startWatering2 = param.asInt();
}

BLYNK_WRITE(V4)
{
  int startWatering3 = param.asInt();
}

BLYNK_WRITE(V5)
{
  int startWatering4 = param.asInt();
}

//watering time values

BLYNK_WRITE(V6)
{
  int wateringTime0 = param.asInt();
}

BLYNK_WRITE(V7)
{
  int wateringTime1 = param.asInt();
}

BLYNK_WRITE(V8)
{
  int wateringTime2 = param.asInt();
}

BLYNK_WRITE(V9)
{
  int wateringTime3 = param.asInt();
}

BLYNK_WRITE(V10)
{
  int wateringTime4 = param.asInt();
}

void loop()
{
  Blynk.run();
  timer.run();
}

where does it fail? ... you have no debugging code in your sketch ... please add code that prints to the serial monitor or code that blinks an LED, so that you can trace the progress of your code

In general it's not a good idea to post actual auth tokens or passwords.

I'm a bit lost with this code--for example, BLYNK_WRITE(V10) creates a local wateringTime4 and immediately returns, throwing it away. I don't think you intended to create a local variable there. The might also need to be volatile, I don't recall.

Tangentially related but the code might be a little easier to reason about if some of this data was encapsulated and shoved into an array or something.

you are brave to use pins 9 and 10. Do you have DOUT as flash mode?

@DaveNewton Whoops I meant to change those... Yeah you're right I didn't mean to create that variable, it was already created above so it could be trying to create an int thats already created causing an error or something. I will fix that and see if it works.

It is getting stuck at the pin initializing, but it gets stuck on different ones each time, sometimes 9 or 10 or 13 and even 4 once.

Ok, I figured out that it is a problem with initializing pin 9 (mux A) and it gives the following error-

wdt reset
load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld```

Ok I got it figured out, it was because I was using pin 9 and 10, I didnt know they couldn't be used. Thanks @Juraj!

I'd start by cutting it down to just the setup() and loop() functions (without the timer call) and establish whether it connects, and if not, why not.
Then add back the timer call and a very short version of checkSensors(), and try again.
Continue adding back sections of code until it fails.


text:
ATmega328p bootloader issue : [avrdude: stk500_recv(): programmer is not responding]
I am using an arduino uno board and have placed the new ATmega328chip in the socket as a simple setup as mentioned in Minicore installation instructions. However, I am unable to burn the bootloader. I am using your minicore and selected the ATmega328 chip. I have tried using 8MHz internal crystal as well as 16 MHz external crystal but get the same error. I even tried using a different ATmega328p but the result was same. Here is the output:
avrdude: Version 6.3-20201216
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\Administrator\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.1.2/avrdude.conf"

         Using Port                    : COM4
         Using Programmer              : stk500v1
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x03
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x03

avrdude done.  Thank you.

Error while burning bootloader.

Before trying this Minicore option I also tried different tutorials which ask for external crystal and extra capacitors. It's been two days I am trying to make it work but sadly haven't managed it yet. Initially I suspected a faulty ATmega but even three other chips result in the same error or device signature error.
Here are the other connections I have used:

Could you please help me fix it? Thanks

Do you have an STK500 Version 1 programmer that you're using to burn the bootloader? Or are you just plugging the Arduino into USB and praying that something miraculously happens?

I don't have that programmer but an AVR asp programmer. For minimal setup I thought I just need to replace the new ATmega in the socket and then then burn the bootloader by plugging the arduino into usb. I didn't even pray though :) May be I didn't understand the minimal setup correctly.

I did also try with the FTDI/UART connection and the ISP to burn the bootloader but was getting a signature error.

I have edited original post with the connection sketches

To program the bootloader you need either a hardware programmer or a working Arduino to use as a programmer. But I am confused (and likely you are too). You say you put the chip in the socket then show us a circuit with a breadboard...

Here is sequence of what I have tried so far. First I tried to burn the bootloader with the ATmega328p & other components on a breadboard following the two different connection schemes shown above.  I got error "avrdude: Yikes! Invalid device signature. Double check connections and try again, or use -F to override this check." At last I simply replaced the ATmega on my working uno board to burn the bootloader.

The former is what you need to do, not the latter. Set it up on a breadboard again and try various tutorials again. Many miss out disabling the Arduino's auto serial reset which you have to do for it to work.

I started a new with clean wiring and tried the tutorial on the arduino website and it does use a pullup resistor on the reset pin. It worked :) Thanks for the pointer

you can't burn bootloader into ATmega by putting it on Uno. even if the ATmega is on Uno you have to use a programmer (or other Arduino as programmer with Arduino as ISP sketch)

@Juraj yeah I misunderstood one of the tutorial. I thought by just placing it on the uno board socket I wouldn't need any external circuitry like caps, resistors and the crystal. Also I would be able to use the serial to usb connection on the board to burn the bootloader. But it's clear now

You have to install the bootloader using either an working Arduino or a hardware programmer.
There is one step that many many tutorials on this subject miss out (and both the circuits you show have missed it out), and that is to disable the automatic reset of the programming Arduino.  That can be done a number of ways:

Add a low-value pullup resistor to RESET
Add a high-value capacitor between RESET and GND
Cut the "RESET-EN" trace on the underside of the board

Once the bootloader is installed in this way you can then put the chip into an Arduino and program it through USB, or connect it to a USB to UART adapter and program it through that.

I used the first method. However, even with a 10K resistor it worked


text:
Do I use an LED or a pullup resistor for stopping "floating" or "ghosting" for a matrix keypad?
I know this sounds simple, but I have an Arduino Mega 2560 and I am making a matrix keypad for a claw machine. It's a 3*4 matrix keypad. Let's just say, I am making this keypad for the claw machine to reduce the number of I/O pins. I have tried to use a mux, but that has failed me because it has a single input/output pin and can only read ONE button at a time. So, I have come up with the solution to use a matrix keypad because: A. It is the most common method and B. It is smaller on a PCB design rather than that CD4067BE chip. The reason why I was trying to use that chip in the first place was because it included all my thirteen buttons. Basically, what I am wanting to know is if I should use a resistor or an LED to stop either "floating" or "ghosting." I still don't really know the difference between the two terms, but if somebody could clarify that, that would be great. And also when I should use an LED or a resistor. Or do they serve the same purpose? Tutorials: LED "ghosting" Pullup Resistor "floating" (I am not sure how to make a schematic of the "floating" pin).  (Credit to EasyEDA for the schematic). Thanks,
Austin

An LED is a diode, but a diode isn't an LED. Note also that matrix keyboards also scan (each row, for example, in the example you link to). I'm still puzzled what human you're targeting that can push buttons faster than an Arduino can scan them.

But, isn't this approach faster? Won't I get a smoother stepper motor ride from them? So, what am I supposed to do about reducing the number of I/O pins from the claw machine?

Thanks for the fast reply, too.

... You're talking about a difference of microseconds. There are a million microseconds in a second. Humans operate in tenths of seconds. A tenth of a second is one hundred thousand microseconds. No human can even perceive, let alone care about, the difference. There are hundreds of examples on making keyboards--just follow one.

Should I go back to the way I had it before? Just the buttons and the INPUT_PULLUP?

failed me because it has a single input/output pin and can only read ONE button at a time ... the matrix keypad is also read one button at a time ... it is like that for almost every device that you use in everyday life, like computer keyboards, TV remote controls, microwave ovens, etc. etc. ... one button is read at a time

Oh, sorry. I wasn't sure.

I really think I should go back to the way I had the PCB before, besides I have a Mega. What could go wrong, right?

I thought I could reduce the most number of I/O pins and complexity of the claw machine buttons. Apparently, I was wrong, it just made things more complex.

Although, I think I could use the matrix design because my code shows that it only reads one button at a time anyway. (For the claw machine). Also, I was using the CD4067BE.

try going with the matrix arrangement ... if it does not work as expected, then go to direct connection, one switch, one pin .... https://playground.arduino.cc/Code/Keypad/

Let us continue this discussion in chat.

First some clarification:

Floating is where an input isn't connected to a defined logic state. It's neither in one state or the other and is free to "float" between them at will. Basically a floating input is an antenna.
Ghosting is where you press two buttons in a matrix together and it causes unwanted short or crossed circuits in the matrix making it appear that other keys are pressed when they aren't.

The Keypad.h library deals with any pullups that may be needed.  To prevent ghosting you need to use diodes (not LEDs) to separate the buttons from each other.
Nick Gammon has a fantastic tutorial where he describes the problems and solutions to ghosting.

So, why can't I use LEDs, does it have to "absorb" more, I guess? Does the Keypad library have internal pullup resistors?

How come the row pins don't have a resistor?

@Austin Libraries have code; hardware has pullup resistors. Because the rows are outputs--only the columns are read. A press is determined by outputting a value on a row and reading all the columns. Read all the way to the bottom :)

That is a good article!

So, how come I can't use LEDs?

LEDs have a massive forward voltage compared to proper diodes. They're also bigger, more power hungry and more expensive.


text:
Click counter using SparkFun Qwiic Twist
I wrote the script below in order to count the number of times that I press the SparkFun Qwiic Twist. But when I press the button, I get series of running numbers on the Serial Monitor and not a counter incrementation by 1. Any ideas how can I solve it?
Script:
#include "SparkFun_Qwiic_Twist_Arduino_Library.h"
TWIST twist;
int twistPressCounter;

void setup() {
  twistPressCounter = 0;
  Serial.begin(9600);

  if(twist.begin() == false)
  {
    Serial.println("Twist does not appear to be connected. Please check wiring. Freezing...");
    while(1);
  }
}

void loop() {
  if(twist.isPressed()) {
    twistPressCounter++;
    Serial.print(twistPressCounter);
}

  Serial.println();
}

Likely because isPressed does no debouncing; try isClicked first.

Thanks a lot for the fast respond

print only when there is a change in the value of twist.isPressed ... right now it prints about 1000 times in one second as long as the button is pressed ... so, if you quickly click the button, then it probably prints about 50 times, or more