text:
How can I observe the "voltage dips" the starter kit talks about in Project 5?
Project 5 of the Arduino Starter Kit book (page 63) involves wiring up a potentiometer to control a servomotor (see diagram). The book also recommends wiring up decoupling capacitors as shown in the diagram:

When a servo motor starts to move, it draws more current than if it were already in motion. This will cause a dip in the voltage on your board. By placing a 100uf capacitor across power and ground right next to the male headers as shown in Fig. 1, you can smooth out any voltage changes that may occur. You can also place a capacitor across the power and ground going into your potentiometer.

Since the book doesn't explicitly warn against it, I decided to do this whole project without the capacitors just to see what would happen. It seemed to work fine, I didn't notice any erratic behavior. Is there some experiment I could do to actually measure these voltage "dips"?
I thought maybe I could try to measure the voltage drop across the servo, so I wired it in series with a resistor and connected the A0 ADC pin between the servo and the resistor. I did measure a drop, but the servo didn't work... I'm guessing it wasn't getting enough power because of the resistor?

I'm guessing it wasn't getting enough power because of the resistor?

Yes, that is probably what happened (you didn't specify what value your resistor had). When the servo tries to draw more current, more current has to flow through the resistor. This means more voltage over the resistor and less for the servo, which then doesn't have enough to to powerful or even run at all (depending on the resistors value).

Is there some experiment I could do to actually measure these voltage "dips"?

You tried to measure the dips with the Arduino. Since the servo is connected directly to the 5V line of the Arduino, so its own Vcc, you cannot measure it the same way as the potentiometer. By default analogRead() uses Vcc as reference, meaning the max value. Instead you can configure it to use the internal 1.1V fixed reference (which doesn't depend on Vcc)(refer to analogReference()) and divide down Vcc with a fixed voltage divider (so that the voltage on the analog input pin would not exceed 1.1V).
Though to see the dips you still would need to measure the data points fast enough to catch them. Without knowing how long the dips might be it is difficult to say, if you can easily catch them. There are ways to do analog measurements relatively fast, but for a beginner (and specifically for a beginner book) that is a bit much.
The easier, but also more expensive solution (in terms of tools) is to measure Vcc with an oscilloscope. As entry a USB oscilloscope might be fitting (in the range of maybe 50$). If you don't wanna buy, you might be able to get access to one at the next makerspace or university. Some schools also might have some oscilloscopes.

Since the book doesn't explicitly warn against it, I decided to do this whole project without the capacitors just to see what would happen. It seemed to work fine

Dips in your supplied voltage might cause the Arduino to reset. But that only happens, when the dip is too big. And that depends on multiple factors:

How much current can be drawn from your power supply. USB ports on a PC won't give you more than 500mA for example. And some battery types have a big series resistance, meaning that the voltage will drop significantly, when you draw too much current from them.
Sometimes, when working on a breadboard, the contacts might also have a significant resistance to them. This can lead to a voltage loss there.
How strong the motor is. In starter kits you typically have these cheap and small SG90 micro servos. These don't draw a lot of power generally and are not really strong.
How much load is on the motor. A motor draws different amounts of current depending on its load. When it runs feely the currently is the smallest. When its starting, then it needs to fight against its own inertia, thus needing more current. The most current is used, when the motor stalls, because it is not powerful enough to push against the load.

The last two points affect the motor current, which might cause a voltage dip, if the power supply cannot provide that much current with the specified voltage.
The capacitors are a precaution in this case. I think the author wanted to explain this to make sure that it would work for everyone and that students would already know about this, when moving to bigger, more power hungry projects.

I tried a 10k resistor and a 220 ohm - with the former the servo didn't budge, with the latter it kind of twitched slowly.


text:
Arduino uno weird behavior on a simple counter program
So I just got my first Arduino Uno board and the output on the serial monitor doesn't make sense to me. For this code
int counter = 0;

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

}

void loop() {
  counter++;
  Serial.println(counter);
  delay(1);
}

I'm expecting to see an increment once every 1ms. But what I see from the console is odd
First, I'm expecting to see the timestamp like this: 27.270, 27.271, 27.272...
Second, from 27.301 to 27.334, I only saw the counter increase by 7 instead of ~30.

If you do something like
Serial.println(580);

that is 5 characters printed (3 digits, then CR and LF to end the
line). Each character takes ten bits worth of transmission time (one
start bit, 8 data bits and one stop bit). The whole message is then
50-bit long on the serial line. At 9600 bits per second, this takes
about 5.2 milliseconds.
Note that the PC seems to be buffering the data, which is displayed in
batches, each batch having a single timestamp. Thus you see that, on
average there are 5.2 ms between increments.

So is there a quick fix to this?

@GotYaLoot: Fix for what? If the problem is, as stated in the question, “the output [...] doesn't make sense to me”, the fix is simply to understand this answer. Is there another problem that would need to be fixed?

I want the serial monitor show something like:
time 0.001 counter=1
time 0.002 counter=2
time 0.003 counter=3

How are you expecting to see a printout every ms when it takes over 5ms to print one line? Also as stated above, when working with serial communication to a PC, there are multiple buffers involved along with the non-real time os that your PC is running. This means there is no way to get ms precision of printed lines with this setup. Its going to be really hard for anyone to give much advise since we have no idea what you are trying to accomplish(big picture wise).

If you increase the baud rate from 9600 to 115200 you will see much faster prints, but you are still at the mercy of the the serial buffers and OS on your pc.

If it takes half an hour to bake a cake, setting a timer for 1 second after you bake the cake, will not make cakes appear every second.

source: Stack Exchange

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

sort: votes


text:
how to config size USB mass storage arduino nano ble 33?
I see that they arduino nano ble 33 support USB 2.0. Is there a way for us to create a USB mass storage of about 200kb for convenient storage of configuration files and history files?
I see example arduino has UsbMassStorage but by default it only creates 1 disk with 512KB capacity. Which 512KB + 200KB bootloader is my chip error.
Is there a way to reconfigure the capacity for UsbMassStorage?
Thank you so much.
    /*
   This example exposes the second half (512KB) of Nano 33 BLE flash
   as a USB disk.
   The user can interact with this disk as a bidirectional communication with the board
   For example, the board could save data in a file to be retrieved later with a drag and drop
*/

#include "PluggableUSBMSD.h"

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

  // write a file with some data
  // a+ means append, so every time the board is rebooted the file will grow by a new line
  FILE *f = fopen("/fs/data.txt", "a+");
  String hello = "Hello from Nano33BLE Filesystem\n";
  fwrite(hello.c_str(), hello.length(), 1, f);
  fclose(f);
}

void loop() {
  delay(1000);
}

which code are you talking about? ... please add the program listing to your question

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


text:
MKR 1010 WIFI Built-in RGB LED not working with BLE
in addition to the standard LED_BUILTIN, MKR 1010 WIFI comes with a built-in RGB LED.
This RGB LED fails when used along the on-board BLE, no matter what program sequence I test.
To reproduce the issue, turn on the LED and then start BLE which will turn the LED off.
#include <WiFiNINA.h>
#include <utility\wifi_drv.h>
#include <ArduinoBLE.h>

void setup() {

  const int ledPin = 27;  //R=26 G=25 B=27

  WiFiDrv::pinMode(ledPin, OUTPUT);

  WiFiDrv::digitalWrite(ledPin, HIGH);

  Serial.begin(115200);
  while (!Serial);

  if (!BLE.begin()) { // ble.begin trun the led off
    Serial.println("BLE Failed");
    while (1);
  }

  Serial.println("BLE started"); // last line shown on console

  WiFiDrv::digitalWrite(ledPin, HIGH);

  // program never gets here

}

void loop() {}

The RGB LED is connected to NINA’s GPIO pins. Two of them (green and blue) are part of the UART, and another one is used for system control signals (red).
I assumed that BLE.begin uses the UART to communicate with the processor and therefore avoided the red pin and added delays between commands hoping to separate the actions, but it didn’t work.
My goal is to use the RGB LED to indicate BLE states without adding three sets of MOSFETs and resistors. Ideas?

The ArduinoBLE library resets the NINA firmware to BLE mode (code here). In this mode the NINA firmware just sets ESP32 SDK (IDF framework) to handle the BLE commands.
The RGB LED is handled by the part of the Arduino NINA firmware which handles the commands from the WiFiNINA library. These commands are communicated over SPI and are not handled if the firmware is in BLE mode.

Appreciate the clarifications, thanks Juraj


text:
Arduino RS485 do I need MAX485?
I'm trying to connect sesnor that use RS485 (I'm almost sure that's modbus). The sensor has RX/TX and +/- wires. Do I still need a component between the RX/TX pin from the Arduino UNO and the sensor itself? All the libraries I reviewed have an additional control pin. Or do I need, for example, a MAX485? Is it possible to simply connect RX of sensor to RX of UNO, TX of sensor to TX of UNO and + to 5V of UNO, and - to - ?

similar question https://arduino.stackexchange.com/questions/53287/dmx-on-the-arduino-without-additional-driver-chip

@Juraj So I need MAX485


text:
change sketch from controlling 8 stepper motors to 8 solenoids
I am looking to see if I can change the attached sketch which controls 8 stepper motors to just switching 8 relays for a weaving loom which we have, unfortunately making this change is well above my paygrade lol. I am using an arduino mega and 8 channel relay board which will in turn trip the solenoids which the loom already has attached, thanks for any help
This is the Sketch im trying to alter

// Loom interface for Ashford Dobby interface (using 8 stepper motors):
// Arduino lines 0 & 1 to USB interface
// line 13 Is foot pedal
// 14-43 are motor controls

// General definitions:
#define MAX_CHARS 80
#define DEBUG 0
#define MOTORS 8
#define IDENTITY "Generic Dobby Interface (Jones Stepper Motor Dobby)\n"

// Data controlling motor positions, states, etc:
const long MOTOR_DELAY=900;                                                      // Time delay between motor steps (reduce till shafts move reliably)
const long  SHAFT_UP=8*170, SHAFT_DOWN=0 ;                                       // Number of motor steps required to raise the shafts
unsigned long shaft_state=0x00000000, shaft_cue=0xffffffff;                      // tracking current & next desired states of shaft controls
long MotorActual[MOTORS], MotorWant[MOTORS];                                     // Current & desired position for each of the motors

// Definition of which Output pins connect to which motor
char MotorPin[MOTORS][4]=                                                        // Motors 1,3,5,7 on right, 2,4,6,8 on left: left side reverses direcion
              { {14,15,16,17}, {18,21,20,19}, {22,23,24,25}, {26,29,28,27},      // Motors 1-4
                {30,31,32,33}, {34,37,36,35}, {38,39,40,41}, {42,45,44,43}};     // Motors 5-8

unsigned long NextMotorUpdate=0;                                                 // Timer for when next motor step occurs
const int ADVANCE  =13;                                                          // input pin for footswitch (has pullup, switch contact only)

// Serial (USB) interface
// Serial interface is a "Generic" dobby interface:
// Host sends which shafts should be activated for current shot
// Shafts will raise when the foot switch is activated
// Shafts return when foot switch is released, and the "Advance" command returned to host
// Also responds to "?" with the "IDENTITY" identified above, shows host who's out here

int serial_chars=0;                                                              // Number of characters in the serial input buffer
char serial_string[MAX_CHARS]="";                                                // Serial input buffer
char Message[MAX_CHARS]="";                                                      // Output message buffer
long serial_time=0;                                                              // Used to close serial string on timeout (timer)
const int serial_timeout=100;                                                    // Digest Serial string after timeout
char serial_idle=1;                                                              // Tracks activity on the serial bus
char HostPresent = 1;                                                            // set when some host is identified
int Button_state=1;                                                              // tracks changes in floor-switch state

////////////////////////////////////////////////////////////////////////
// Send shaft controls to hardware
////////////////////////////////////////////////////////////////////////
    void set_motor(char m,char state)                                            // Lowest level function to handle step in motors
    {
//   sprintf(Message,"M %d @ state %d\n",m,state);
//   Serial.write(Message);
     switch(state)
     {
      case 0:                                                                    // Set motor inactive
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 1:                                                                    // Set motor State 1
      digitalWrite(MotorPin[m][0], 1);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 2:                                                                    // Set motor state 2
      digitalWrite(MotorPin[m][0], 1);    digitalWrite(MotorPin[m][1], 1);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 3:                                                                    // Set motor state 3
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 1);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 4:                                                                    // Set motor state 4
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 1);
      digitalWrite(MotorPin[m][2], 1);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 5:                                                                    // Set motor state 5
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 1);    digitalWrite(MotorPin[m][3], 0);
      break;

      case 6:                                                                    // Set motor state 6
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 1);    digitalWrite(MotorPin[m][3], 1);
      break;

      case 7:                                                                    // Set motor state 7
      digitalWrite(MotorPin[m][0], 0);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 1);
      break;

      case 8:                                                                    // Set motor state 8
      digitalWrite(MotorPin[m][0], 1);    digitalWrite(MotorPin[m][1], 0);
      digitalWrite(MotorPin[m][2], 0);    digitalWrite(MotorPin[m][3], 1);
      break;
     }
    }

   char set_motors()                                                            // Set all motors to new motor state - called for each motor step on any motor
    {                                                                            // return indicates if any motor is still active
     int m=0;
     long setting, entry_setting;
     char active=0;

     while(m<MOTORS)
     {
                                                                                // Check for necessary directional movement
      entry_setting=setting=MotorActual[m];
      if(setting==MotorWant[m])       setting=setting;
      else if(setting<MotorWant[m])   setting++;
      else                            setting--;
                                                                                // Send update setting controls
      if((entry_setting!=MotorWant[m]))
      {
       active=1;
       MotorActual[m]=setting;                                                   // update actual for move in progress
       setting=(setting&7)+1;                                                    // set_motor state 0 is inactive, 1-8 are active
       set_motor(m,setting);                                                     // Set new motor state
      }
      m++;                                                                       // Next motor
     }
     if(active==0)
     {                                                                           // If done kill power to the motors that are back in passive state
      m=0;
      while(m<MOTORS)
      {
       if(MotorActual[m]==SHAFT_DOWN)set_motor(m,0);                             // set motor inactive
       m++;
      }
     }
     return active;
    }

    char run_motors()                                                            // Higher level function to set motors to desired positions
    {                                                                            // return indicates if motors are active or idle
     char active=1;
     if(micros()>=NextMotorUpdate)
     {                                                                           // time to update the motor positions
      active=set_motors();                                                       // Update all motors
      NextMotorUpdate=micros()+MOTOR_DELAY;                                      // set clock for next update
     }
     return active;
    }

    void set_shafts(unsigned long shafts)                                        // Called to set desired motor positions based on which shafts were requested
    {                                                                            // This assumes all shafts move the same amount, they really don't need to
     unsigned long bit_mask=1;
     int i=0;
     while(i<MOTORS)
     {
      if(shafts&bit_mask)MotorWant[i]=SHAFT_UP;
      else               MotorWant[i]=SHAFT_DOWN;
//    sprintf(Message,"M %d @ want %d\n",i,MotorWant[i]>>8);
//    Serial.write(Message);
      i++;
      bit_mask=bit_mask<<1;
     }
    }
////////////////////////////////////////////////////////////////////////
// Preset- Called on initialization
////////////////////////////////////////////////////////////////////////
    void preset()                                                                // Could raise all shafts to show it's working, etc.
    {                                                                            // This version doesn't do anything, default will lift all shafts when the foot switch is pressed before anything else is requested
    }

//////////////////////////////////////////////////
// SERIAL INTERFACE (USB) FUNCTIONS
//////////////////////////////////////////////////
                                                                                // USB input commands:
                                                                                // 1,2,3,n            Set shafts 1,2,3,n
                                                                                // ?                  ID request, respond with ID
    unsigned long get_shafts(char* command)                                      // Input is series of numbers, comma seperated, for shafts to raise
    {                                                                            // returns word indicating which shafts were identified in string
     int chars=strlen(command);                                                  // Number of characters in input string
     int i=0;
     unsigned long shafts=0, bits;                                               // Sets bits for shafts indicated
     char shaft=0, digit=0, character;

     while(i<=chars)                                                             // loop through all characters in command
     {
      character=command[i];

      if((character==',')||(i==chars))
      {                                                                          // have field seperator or end of string, not shaft desired
       if((shaft>0)&&(shaft<=32))
       {                                                                         // 'shafts' notes this shaft is required
        bits=1<<shaft-1;
        shafts|=bits;
        shaft=0;
       }
      }
      else if(('0'<=character)&&(character<='9'))
      {                                                                          // have digit
       character&=0x0f;                                                          // reduce to decimal
       shaft=shaft*10+character;
      }
      else if((character==' ')||(character=='\n'));                              // ignore spaces/returns
      else
      {
       Serial.println("Invalid Character detected in command:");                 // debug display of command extracted
       Serial.println(command);                                                  // debug display of command extracted
       i=chars;                                                                  // quit, got crap
      }
      i++;
     }
     return shafts;
    }

    void digest_serial(char* command)                                            // Main serial response function
    {
     int chars=strlen(command);                                                  // Number of characters in command

     if(chars>0)
     {                                                                           // If something to do go digest the input
      HostPresent=1;                                                             // note that there's something out there talking to me
      if(('0'<=command[0])&&(command[0]<='9'))                                   // go number, should be shafts
       shaft_cue=get_shafts(command);                                            // convert ASCII string to binary word
      else  if((command[0]=='c')||(command[0]=='t'))                             // test command to cycle valves
       preset();                                                                 // cycle through the valves (nothing defined for this loom, could implement shaft self test, etc)
      else if(command[0]=='?')
      {                                                                          // Have a "Who are You?" kind of command, tell host who we are
       char message[256]=IDENTITY;                                               // Build primary Identity command
       message[strlen(message)-1]=0;                                             // delete return in line
       sprintf(message,"%s  [Solenoid state = 0x%3x]\n",message,shaft_state);    // note what we'll do when button is pressed
       Serial.write(message);                                                    // Send identity with current switch state to host (for troubleshooting)
      }
     }
    }

    void serial_input()
    {                                                                            // High level Serial processing
     char inChar;
     char command[MAX_CHARS]="";

     while((Serial.available()>0))
     {                                                                           // Get serial command from host (character by character)
      inChar=char(Serial.read());
      serial_string[serial_chars]=inChar;
      serial_chars++;
      serial_string[serial_chars]=0;
      serial_time=millis();
     }
     if((serial_chars>0)&&(serial_idle)&&((serial_string[serial_chars-1]=='\n')||(millis()>(serial_time+serial_timeout))))
     {                                                                           // If have a command, go digest it
      serial_idle=0;
      strcpy(command,serial_string);
      serial_chars=0;
      serial_string[0]=0;
//    Serial.println(command);                                                   // debug display of command extracted
      digest_serial(command);
                                                                                // done with last command, clear the input buffers
      serial_idle=1;                                                             // ready for more serial input
     }
    }

////////////////////////////////////////////////////////////// /
// Foot Switch monitor  - set shafts/tell host to advance
////////////////////////////////////////////////////////////// /
    void monitor_button()
    {                                                                            // check for button push to advance, sent only when button pushed (not held)
     char state=digitalRead(ADVANCE);                                            // read state of foot switch (0=active, 1=inactive)

     if(state==0)
     {                                                                           // button is pressed,
      set_shafts(shaft_cue);                                                     // Set motor desired states from the list of shafts desired for this shot
      run_motors();                                                              // Go run the motors to make it happen
     }
     else
     {                                                                           // button is not pressed,
      set_shafts(0);                                                             // Set motor desired states back to reset condition
      run_motors();                                                              // Make it happen
      if(Button_state!=state)
       Serial.write("ADVANCE\n");                                                // Send "Advance" when foot switch is released
     }
     if(state!=Button_state)                                                     // Check if button has changed state
      delay(500);                                                                // Wait half a second on changes to debounce switch
     Button_state=state;                                                         // Track current state of the button to look for changes
    }

//////////////////////////////////////////////////
// TOP LEVEL FUNCTIONS - SETUP & LOOP                                                                                //
//////////////////////////////////////////////////
    void setup()
    {
     char m;                                                                     // Motor indicator

                                                                                // USB Interface to host computer
     Serial.begin(9600);                                                         // start serial port at 9600 bps:
     Serial.print(IDENTITY);                                                     // print message on serial monitor

                                                                                // Motor Controls
                                                                                // set motor controls for all motors
     m=0;
     while(m<MOTORS)
     {
      digitalWrite(MotorPin[m][0], LOW);                                         // set low
      digitalWrite(MotorPin[m][1], LOW);                                         // set low
      digitalWrite(MotorPin[m][2], LOW);                                         // set low
      digitalWrite(MotorPin[m][3], LOW);                                         // set low
      pinMode(MotorPin[m][0], OUTPUT);                                           // Set as output bit
      pinMode(MotorPin[m][2], OUTPUT);                                           // Jumble order to keep motor from moving
      pinMode(MotorPin[m][1], OUTPUT);                                           // Set as output bit
      pinMode(MotorPin[m][3], OUTPUT);                                           // Set as output bit
      MotorWant[m]=MotorActual[m]=0;                                             //
      m++;
     }

      pinMode(ADVANCE, INPUT_PULLUP);                                            // Set as input pin to handle the foot switch
      preset();                                                                  // "self test" - note it's alive
      unsigned long T0=millis();                                                 // Note start up time
     }

    void loop()
    {
     serial_input();                                                             // check the serial interface, handle if it comes in
     monitor_button();                                                           // check for button push
    }

it's not possible to do what you want without knowing how the solenoid action replaces the motor action ... basically, what the motors do, at what time do they do it, and how do the solenoids replace the function that the motors do

comments are not part of the code ... they should not be interweaved into the code ... cleaned up the program listing for you

Hi Jsotola, thankyou for your reply, all the solenoid will do is activate when the motor would normally, ie instead of the motor engaging and doing x number of rotations the solenoid will just engage, this is triggered by the software that is running on windows to create and run a pr determined pattern, then when the foot switch is triggered the solenoid will disengage and the pc software will move to the next step in the pattern and engage the correct solenoids. sorry about all of the comments as these were already in the sketch that I found.

lots of comments are a very good thing, but they should not clutter the code ... that's all I'm saying

I always thought the best place for comments are at the beginning of the functions. Good comments there indicate thought went into segmenting the task into nicely organized functions. However, even the giants like NXP and STMicro do not regularly do this in their code. Also, comments like "Set motor State 1" are worthless. Seasoned programmers will instantly comment: "That's obvious ... but what is 'State 1' ... that's the real question / comment to be made."

The assumed goal is to automate a Weaving Loom using solenoids instead of steppers.

This video claims a 3kg pull is necessary. It may be difficult to find an appropriate / economical solenoid with that kind of pull, stroke distance & rated for continuous duty (hold its position for a prolonged period of time without harming its self from heat related problems).

If sourcing such a solenoid is not a problem, there are only 2 functions in the above code that control the steppers. "set_motor" and "setup". Change those to activate / deactivate solenoids.

Also, this might be harder, remove the code that cycles the steppers into / out-of position. You don't need that w/the solenoids.

I would first figure out what each stepper motor code segment is doing, in overview. Think of viewing the process while standing back from it and describe the reason that code segment is there, more than what, specifically, it does - what it's relationship is to the process, not to the motor.
Move those motor segments into functions, and put function calls where the motor segments used to be.
Now replace the motor code inside each function with solenoid code. This is why we wanted an abstract overview of those motor segments. In each function, you'll write solenoid-specific code that has that same relationship to the overall process as the motor code did, but you'll tailor the specifics to the solenoids.


text:
Arduino MEGA crashes with Ethernet shield to connect to two TCP servers
I have Arduino MEGA with Ethernet Shield and a SD card connected to a RUT950 GSM router. Then, I also have two sensors connected to the router and they run a TCP server that sends measurements character after character with a "\n" to terminate the measurement.
I got this from the uSonic Wind Sensor:
    $WIMWV,000.0,R,00.0,M,A*10\n
    $WIMTA,022.8,C*23\n
    $WIMHU,083.3,,019.8,C*05\n
    $WIMMB,,,1006.8,B*0F\n

Sensor 1, local IP: 192.168.1.200, port 1649
Sensor 2, local IP: 192.168.1.201, port 1647
Router: 192.168.10.1
Arduino: 192.168.10.100
My program reads from the two TCP servers, store the readings in a char buf[] and then it saves them into a SD card. Then, the program load the file and sends it to the FTP server.
This works fine sometimes, other times it crashes or it starts receiving the data from the two sensors but after some minute, it appears to received only from one sensors or it receives nothing at all. It is very strange! Sometimes, it sends the file only the first time and so on. It has a really random behaviour and I cannot understand why!
Can you help me please?
The sensors have only a public ip address so you can try the code on your pc, if you want to (I can give you the public ip address).
// Library includes
#include <SD.h>
#include <FTP.h>
#include <RTC.h>
#include <Ethernet.h>

// Set Ethernet properties of our PLC
uint8_t mac[] = { 0xDE, 0xAD, 0x4E, 0x55, 0xFE, 0xED };
IPAddress ip(192, 168, 10, 100);
IPAddress netmask(255, 255, 255, 0);
IPAddress server(2, 45, 150, 21);

byte server_svs60[] = { 192, 168, 10, 201 };  // Touchberry Pi Server
int tcp_port_svs60 = 4197;
byte server_wind[] = { 192, 168, 10, 200 };  // Touchberry Pi Server
int tcp_port_wind = 4196;
EthernetClient client_svs60;
EthernetClient client_wind;

const byte numChars = 32 * 4;
char receivedChars[numChars + 1];
char tempChars[numChars + 1];  // temporary array for use when parsing

const byte numChars_wind = 32 * 4;
char receivedChars_wind[numChars + 1];
char tempChars_wind[numChars + 1];  // temporary array for use when parsing

byte lineCount = 0;

IPAddress time_server(147, 156, 7, 26);  // es.ntp.pool.org
unsigned int udpPort = 2390;
EthernetUDP udp;
const int NTP_PACKET_SIZE = 48;      // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE];  //buffer to hold incoming and outgoing packets

// Variable to save the hour and second
int savedHour;
int savedSecond;
char datetime[50];
// Variables to manage the SD card
Sd2Card card;
SdVolume volume;

bool flag_wind = false;
bool flag_svs60 = false;

// Define the variables for FTP management
EthernetClient ftpControl;
EthernetClient ftpData;
FTP ftp(ftpControl, ftpData);

// Setup function
void setup() {
  // Set the speed of the serial port
  Serial.begin(9600);

  // Init the SD Card
  if (!SD.begin(53)) {
    Serial.println("Card failed, or not present");
    while (true)
      ;
  }

  // Configure the ethernet protocol in our PLC
  Ethernet.begin(mac, ip, netmask);
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());

  if (client_svs60.connect(server_svs60, tcp_port_svs60)) {
    Serial.println("Connected to the SVS60 server");
    client_svs60.println();
  } else {
    Serial.println("Connection to the SVS60 TCP Server failed");
  }
  delay(1000);

  if (client_wind.connect(server_wind, tcp_port_wind)) {
    Serial.println("Connected to the Wind server");
    client_wind.println();
  } else {
    Serial.println("Connection to the Wind Server failed");
  }

  int c = ftp.connect("2.45.150.21", "geoatlas", "Datiboa2023@");
  while (!c) {
    delay(1000);
    c = ftp.connect("2.45.150.21", "geoatlas", "Datiboa2023@");
  }

  udp.begin(udpPort);
  sendRequest();
}

// Loop function
void loop() {
  Serial.println("parsePacket");
  if (udp.parsePacket()) {

    udp.read(packetBuffer, NTP_PACKET_SIZE);

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    const unsigned long seventyYears = 2208988800UL;
    unsigned long epoch = secsSince1900 - seventyYears;

    RTC.setTime(epoch);
    RTC.write();
  }
  Serial.println("rtc read");
  if (!RTC.read()) {
    Serial.println("Read date error: is time set?");
  } else {
    //filename_sd = String(RTC.getYear() + String("") + RTC.getMonth() + String("") + RTC.getMonthDay() + String(".txt"));

    sprintf(datetime, "%04d-%02d-%02d %02d:%02d:%02d",
            RTC.getYear(), RTC.getMonth(), RTC.getMonthDay(),
            RTC.getHour(), RTC.getMinute(), RTC.getSecond());
  }
  // Serial.println(datetime);
  Serial.println("svs60");
  if (client_svs60.available()) {
    Serial.println("dentro svs60 sensor");
    char c = client_svs60.read();
    Serial.println(c);
    strncat(tempChars, &c, 1);
    if (c == '\n') {
      strcpy(receivedChars, tempChars);
      strcpy(tempChars, "");
      Serial.println("I got this from SVS60: ");
      Serial.println(receivedChars);
      logToSd_svs60(receivedChars);
      sendToFTP();
     // memset(0, receivedChars, sizeof(receivedChars));
    }
  }
 Serial.println("wind sensor");
  if (client_wind.available()) {
    Serial.println("dentro wind sensor");
    char c1 = client_wind.read();
    Serial.println(c1);
    strncat(tempChars_wind, &c1, 1);

    if (c1 == '\n') {
      if (++lineCount == 4) {
        strcpy(receivedChars_wind, tempChars_wind);
        strcpy(tempChars_wind, "");
        lineCount = 0;
        Serial.println("I got this from the uSonic Wind Sensor: ");
        Serial.println(receivedChars_wind);
        logToSd_wind(receivedChars_wind);
       // memset(0, receivedChars_wind, sizeof(receivedChars_wind));
      }
    }
  }

  delay(200);
}

// Function to save information to SD
void logToSd_svs60(char value[]) {
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    Serial.println("Saving SVS60 to SD");
    dataFile.println("Sensore Ondametrico: ");
    dataFile.println(datetime);
    dataFile.println(value);
    dataFile.close();
  } else {
    Serial.println("Error opening datalog.txt");
    while (true)
      ;
  }
}

// Function to save information to SD
void logToSd_wind(char value[]) {
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    Serial.println("Saving Wind to SD");
    dataFile.println("Dati sistema: ");
    dataFile.println(datetime);
    dataFile.println(value);
    dataFile.close();
  } else {
    Serial.println("Error opening datalog.txt");
    while (true)
      ;
  }
}

unsigned long sendRequest() {
  memset(packetBuffer, 0, NTP_PACKET_SIZE);

  packetBuffer[0] = 0b11100011;  // LI, Version, Mode
  packetBuffer[1] = 0;           // Stratum, or type of clock
  packetBuffer[2] = 6;           // Polling Interval
  packetBuffer[3] = 0xEC;        // Peer Clock Precision
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;

  //Serial.println("I check the time server");

  if (!udp.beginPacket(time_server, 123)) {
    Serial.println("Begin packet error");
  } else {
    udp.write(packetBuffer, NTP_PACKET_SIZE);
    if (!udp.endPacket()) {
      Serial.println("End packet error");
    }
  }
}

void sendToFTP(void)
{
  Serial.println("SD.open");
  // Open the SD file
  File dataFile = SD.open("datalog.txt");

  // Check if the file was succesfully open
  if (dataFile)
  {
        Serial.println("Sending trough FTP connection");
        ftp.store("datalog.txt", dataFile);
        dataFile.close();

  }
  else
  {
        Serial.println("Error opening2 datalog.txt");
        while (true)
          ;
  }
}

did you try some recovery like reconnect when connected() returns false?

But the problem is that I'm not sure the problem is related to a loss of connection. Moreover, I call the client.connect() inside the setup() so I do not know if I can check it inside the loop function. Should I check if client is connected inside the loop function just before client.available? But in this way, should I change also the control of the received characters?

I do not know if I can check it inside the loop function. ... examine the example code that is included with the ethernet library ... ask questions after

Probably I solved the system by checking if the client is connected and also by re-connecting it at some time interval.


text:
Debug Macro Not working
I wrote simple program to test debug macros, but it gives me compilation error
Program:
#include <Arduino.h>

#define DEBUG

#ifdef DEBUG
  #define DPRINT(...)    Serial.print(__VA_ARGS__)
  #define DPRINTLN(...)  Serial.println(__VA_ARGS__)
#else
  // define blank line
  #define DPRINT(...)
  #define DPRINTLN(...)
#endif

void setup() {
  // put your setup code here, to run once:
  String str ="Hello MrNams";
  DPRINT("Here is my string %s",str);
}

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

Compilation Error:
src/main.cpp: In function 'void setup()':
src/main.cpp:7:50: error: no matching function for call to 'HardwareSerial::print(const char [21], String&)'
#define DPRINT(...)    Serial.print(VA_ARGS)
^
src/main.cpp:19:3: note: in expansion of macro 'DPRINT'
DPRINT("Here is my string %s",str);
^~~~~~
In file included from C:/Users//.platformio/packages/framework-arduinoespressif32/cores/esp32/Stream.h:26,
from C:/Users//.platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h:177,
from src/main.cpp:2:
C:/Users//.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h:81:12: note: candidate: 'size_t Print::print(const __FlashStringHelper*)'
size_t print(const __FlashStringHelper *);
^~~~~
C:/Users//.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h:81:12: note:   candidate expects 1 argument, 2 provided
C:/Users//.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h:82:12: note: candidate: 'size_t Print::print(const String&)'
size_t print(const String &);

Serial.print doesn't support variable arguments

format the error log as code

This: ("Here is my string %s",str); cannot be handed over to Serial.print() which is effectively what you are doing. The argument set appears to be more appropriate for the C++ function printf().


text:
Arduino resets or stuck during run, only when DC motors are connected
I'm using an arduino connected to 2 DC motors through L298N. the arduino is powered by a 9V battery, and the L298N is powered by 4 AA batteries. there's also a switch that starts the movement.
I've added print statements to debug, one in the setup, one in the start of the loop, and two before and after running so i know when the motors start and how long they run. I also print the state of the switch. this is what i get:
1                          // switch state. 1  means off.
loop                       // start of loop statement
1
loop
0                          // switch state changed to on
0                          // added another switch check after the if
Forward for: 5 seconds     // motors on
setup                      // reset for some reason
loop                       // start of loop
0                          // switch still on
setup                      // another reset
loop
0
0
Forward for: 5 seconds     // motor starts again
setup                      // another reset
loop
0
0
Forward for: 5 seconds     // stuck with the motors on, no more resets

its not always this bad, sometimes it runs once or twice correctly (for five seconds) and then off. some times it gets stuck on without reseting. also, sometimes it starts reading the switch value as 1 after a few seconds of reading the correct value, even though the switch wasen't moved. also, when I remove one of the motor batteries so they don't get power everything works great.
What causes the reset and the freezing? How can I fix that?
this is my code:
#include <Arduino.h>
int RightSpeedPin = 5;
int Rdir2 = 6;
int Rdir1 = 7;
int led = 13;
int LeftSpeedPin = 10;
int Ldir2 = 8;
int Ldir1 = 9;
int SwitchPin = 4;
int ReadVal;
int baseSpeed = 230;
int Stime;
int Etime;

void go(int d) { // d = 1 will move, d = 0 will stop
  analogWrite(RightSpeedPin, (d == 1 ? 230 : 0));
  analogWrite(LeftSpeedPin, (d == 1 ? 255 : 0));
}

void forward(int t) {
  Serial.print("Forward for: ");
  Serial.print(t / 1000);
  Serial.println(" seconds");
  digitalWrite(Rdir1, HIGH);
  digitalWrite(Ldir1, HIGH);
  digitalWrite(Rdir2, LOW);
  digitalWrite(Ldir2, LOW);
  digitalWrite(led, HIGH);
  Stime = millis();
  while (millis() < Stime + t) {
    go(1);
  }
  go(0);
  Etime = millis();
  Serial.print("ran for ");
  Serial.println(Etime - Stime);
  digitalWrite(led, LOW);
}

void spin() {
  digitalWrite(Rdir1, LOW);
  digitalWrite(Rdir2, HIGH);
  digitalWrite(Ldir1, HIGH);
  digitalWrite(Ldir2, LOW);
  Stime = millis();
  while (millis() < Stime + 100) {
    go(1);
  }
  go(0);
}

void setup() {
  // put your setup code here, to run once:
  pinMode(Rdir1, OUTPUT);
  pinMode(Rdir2, OUTPUT);
  pinMode(RightSpeedPin, OUTPUT);
  pinMode(LeftSpeedPin, OUTPUT);
  pinMode(Ldir1, OUTPUT);
  pinMode(Ldir2, OUTPUT);
  pinMode(SwitchPin, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  Serial.println("setup");
}

void loop() {
  Serial.println("loop");
  ReadVal = digitalRead(SwitchPin);
  Serial.println(ReadVal);
  if (!ReadVal) {
    delay(500);
    Serial.println(ReadVal);
  // starting situation- both motors heading forward
    // running for 5 secs
    forward(5000);
    delay(1000);
    spin();
  }
}

and this is my scheme:

Does it also freeze if you remove the motors (not their batteries)?

didn't try since it doesn't freeze when i remove the battery. i didn't think removing them completely might have a different result.

Micro processor pull up resistors can vary greatly.  If pulling the motors improves the expected behavior, consider adding a 1K (1K/3V = 3mA) pull up resistor to the enable / disable switch.  If that improves things, try increasing it to 10K (10K/3V = 0.3mA).  As you want to draw as small a current as possible to extend battery life.  Also, avoid routing 9V and 6V battery wires in parallel as much as possible.

@st2000 the problem is that the Arduino is resetting and freezing mid run when the motors are connected, why do you think the pull up resistor is the cause here? I don't get any problems when the motors aren't powered, and the resistor is still in use.
the 9V is connected to the Arduino barrel jack, the 6V is connected to the L298N and the negative rail. there's no crossing.

This looks a bit like the motor driver is causing a voltage drop for the microcontroller, causing it to freeze or reboot. Probably one of the digital lines is drawing to much power, which could be caused by a defective motor driver board.

Brush DC motors (assumed what is being used) are making and breaking contact with inductive loads with each revolution.  That is a lot of noise!  Most small motors come with small capacitors across their input terminals to mitigate problems.  The schematic looks correct. And the code has activated the internal pull up resistor on the enable input.  But if the internal pull up resistor was large, noise could induce a high enough voltage to unexpectedly disable the motors.  Or, perhaps, with enough noise, the processor may see enough supply voltage variation that it unexpectedly resets.

The L298 has a pair of darlington bipolar transistors in each motor lead. This will cause a voltage drop of at least 1.4V or 2.8V to the motor, starving it of power. This is burnt up as heat which your battery is supplying. Also a 9V smoke alarm battery is a bad choice for powering an Arduino even though many place show using it as a power source.

The L298 has a pair of darlington bipolar transistors in each motor lead. This will cause a voltage drop of at least 1.4V on each lead or 2.8V to the motor, starving it of power. This voltage drop is burnt up as heat which your battery is supplying. A 9V smoke alarm battery is a bad choice for powering an Arduino even though many place show using it as a power source. Take a look at this link, it has some nice graphs showing just how much the voltage drop will be.
https://www.powerstream.com/9V-Alkaline-tests.htm The maximum current draw of the Arduino R3 is in the range of 200mA. Try connecting several 9V batteries in parallel and if the problem disappears should the 9V battery.

When brushed motors are involved I usually think of arc suppression caps across the motor terminals, 100 mF or larger cap across the motor power supply, solid common (GND) connections. Sparking motor commutators can cause all sorts of problems.

I've tried with a 4700uF 16V cap  across the motor driver and the common ground, its the highest F i could get and it did nothing. should i order a stronger cap online?


text:
ArduinoJson buffer corruption
I have a very wierd behavior using two different ArduinoJson (6.17.3) objects on my ESP32. I was not able to reproduce it in a small example but could track it down to some extent.
From MQTT I receive a json string payload (actually it is a const char*) looking like this:
{"getLog": {"BOOL": false}, "restartESP": {"BOOL": false}, "config": {"M": {"cRI": {"N": "1200000"}, "cST": {"N": "120000"}, "SSID": {"S": "smartabell"}, "cAL": {"BOOL": true}, "PW": {"S": "smartabell"}}}, "OTA": {"S": "99"}, "time": {"S": ""}, "updateConfig": {"BOOL": false}, "MAC": {"S": "84:CC:A8:00:E7:94"}}

I store it in
DynamicJsonDocument mqttJsonDoc(MY_MQTT_MAX_PACKET_SIZE);
deserializeJson(mqttJsonDoc, payload);

for further parsing, which works fine at the beginning. However, when I call the following function to ACK the MQTT package (it is called in the same function where mqttJsonDoc is created):
bool ackDDBAction(const char *new_val, const char *ack_pub_topic)
{
    /* JSON settings */
    DynamicJsonDocument ackJsonDoc(MQTT_MAX_ACK_SIZE);
    ackJsonDoc["MAC"] = MAC_str;
    ackJsonDoc["ACK"] = "";
    ackJsonDoc["updateConfig"] = new_val;
    /* Calculate buffer length */
    size_t jsonSize = measureJson(ackJsonDoc) + 1;
    char jsonBuffer[jsonSize];
    /* Serialize json object into a char array */
    serializeJson(ackJsonDoc, jsonBuffer, jsonSize);
    /* Send ack */
    ack_success = client.publish(ack_pub_topic, jsonBuffer);

    return ack_success;
}

Somehow my original json object mqttJsonDoc is corrupted and looks like:
{"getLog":{"BOOL":false},"restartESP":{"BOOL":false},"config":{"M":{"cRI":{"N":"1200000"},"cST":{"N":"120000"},"SSID":{"S":"smartabell"},"cAL":{"BOOL":true},"PW":{"S":"smartabell"}}},"OTA":{"S":"99"},"time":{"S":""},"updateConfig":{"BOOL":false},"MAC":{"S":"84:CC:A8:00:E7:94"}}{"ub{\"MAC\":\"84CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":{"\":\"84CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":false},"CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":{",\"ACK\":\"\",\"getLog\":\"0\"}0000":false},"\":\"\",\"getLog\":\"0\"}0000":{"etLog\":\"0\"}0000":{"Log\":\"0\"}0000":{":\"0\"}0000":"0\"}0000"},"cST":{"N":"120000"},"SSID":{"S":"smartabell"},"cAL":{"BOOL":true},"PW":{"S":"smartabell"}}},"OTA":{"S":"99"},"time":{"S":""},"updateConfig":{"BOOL":false},"MAC":{"S":"84:CC:A8:00:E7:94"}}

The beginning is similar, but in the middle, fragments of the other jsonDocument ackJsonDoc appear. Besides, it is full of escape chars \. After some debugging, I found out that only when the line serializeJson(ackJsonDoc, jsonBuffer, jsonSize); is executed mqttJsonDoc gets corrupted.
I played around with dynamic and static json document but it didnt change the behavior, besides out of curiosity, I created another json object to see if somehow there was a memory overlap.
    DynamicJsonDocument mqttJsonDoc2(MY_MQTT_MAX_PACKET_SIZE);
    deserializeJson(mqttJsonDoc2, payload);

But this additional dynamic json document holding the payload as well, is corrupted when ackDDBAction() is called, too. Increasing any of the json objects by size did not lead to an improvement as well.
I was looking for known issues and cavities but didnt find anything in the documentation https://arduinojson.org/v6/api/json/serializejson/.
But maybe someone has an idea or faced this issue before - I could do some work arounds but they would be ugly and I would like to understand what is happening here.


text:
how to change output PWM based on analog input
I want to give different PWM (D11) signals based on how much voltage is input (A7). How can I change PWM for different analog values?
#include <LiquidCrystal.h>
#include <ezButton.h>

ezButton button(7);
int count;
int count1;

const float Pin0=A0;
const float Pin1=A1;
const float Pin2=A2;
const float Pin7=A7;

float valueA;
float valueB;
float valueC;
int valueD;

const float rs = 1, en = 2, d4 = 3, d5 = 4, d6 = 5, d7 = 6;

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  TCCR2B = 0b00000001; // x1
  TCCR2A = 0b00000011; // fast pwm
  pinMode(11, OUTPUT);
  pinMode(9, OUTPUT);
  button.setDebounceTime(5); // set debounce time to 50 milliseconds
  button.setCountMode(COUNT_FALLING);
  lcd.begin(16, 1);
  pinMode(Pin0, INPUT);
  pinMode(Pin1, INPUT);
  pinMode(Pin2, INPUT);
  pinMode(Pin7, INPUT);
}

void loop() {
  float a;
  float b;
  float c;

  valueD = analogRead(Pin7);

  digitalWrite(9, HIGH);
  digitalWrite(9, LOW);
  valueA = analogRead(Pin0);
  digitalWrite(9, HIGH);

  a = valueA * 5 / 1023;
  b = valueB * 5 / 1023 * 1.91 - a;
  c = valueC * 5 / 1023 * 0.182;

  valueB = analogRead(Pin1);
  valueC = analogRead(Pin2);

  button.loop();
  int count = button.getCount();
  count1 = constrain(count, 0, 4);
  if (count1 == 0) {
    lcd.print("Bal-Chg");
  }
  if (count1 == 1) {
    lcd.print("V1: ");
    lcd.print(a);
    lcd.print("V");
  }
  if (count1 == 2) {
    lcd.print("V2: ");
    lcd.print(b);
    lcd.print("V");
  }
  if (count1 == 3) {
    lcd.print("I:");
    lcd.print(c);
    lcd.print("A");
  }
  if (count1 == 4) {
    button.resetCount();
  }

  delay(500);
  lcd.clear();
}

https://www.gammon.com.au/forum/?id=11504&reply=6#reply6 is an example of using a potentiometer (on an analog input) to control the duty cycle of hardware timer. This is example is especially useful if you don't want to work with standard frequencies that analogWrite() restricts you to.

Are you using an Arduino UNO or some other processor?

The map() function can help. Supply it the minimum and maximum possible values of the A/D output, and the minimum and maximum inputs to the PWM. (This as assuming you expect the full range of inputs and want the full range of outputs.) It will do the calculations for you. You'll have to code reading the A/D and writing the PWM.


text:
I want to have separate Keypad passcodes to light up an RGB and run a DC Motor in one code. 6113 for RGB and 4613 for the DC Motor
#include <Keypad.h>

const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 3; //three columns

const int PIN_RED = 2;
const int PIN_GREEN = 3;
const int PIN_BLUE = 4;

const int MOTOR_PIN1 = 5;
const int MOTOR_PIN2 = 13;

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};

byte pin_rows[ROW_NUM] = {12, 11, 10, 9};
byte pin_column[COLUMN_NUM] = {8, 7, 6};

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );

const String password_1 = "6113";
const String password_2 = "4613";
String input_password;

void setup(){
  Serial.begin(9600);
  input_password.reserve(32); // maximum input characters is 33, change if needed
}

void loop(){
     loop_RGB();
     loop_DCMOTOR();
}

void loop_RGB(){
  char key = keypad.getKey();

  if (key){
    Serial.println(key);

    if(key == '*') {
      input_password = ""; // reset the input password
    } else if(key == '#') {
      if(input_password == password_1) {
        Serial.println("password is correct");

  analogWrite(PIN_RED,   255);
  analogWrite(PIN_GREEN, 0);
  analogWrite(PIN_BLUE,  0);

  delay(1000); // keep the color 1 second

  analogWrite(PIN_RED,   0);
  analogWrite(PIN_GREEN, 255);
  analogWrite(PIN_BLUE,  0);

  delay(1000); // keep the color 1 second

  analogWrite(PIN_RED,   0);
  analogWrite(PIN_GREEN, 0);
  analogWrite(PIN_BLUE,  255);

  delay(1000);
      } else {
        Serial.println("password is incorrect, try again");
      }

      input_password = ""; // reset the input password
    } else {
      input_password += key; // append new character to input password string
    }
  }
}

void loop_DCMOTOR(){
  char key = keypad.getKey();

  if (key){
    Serial.println(key);

    if(key == '*') {
      input_password = ""; // reset the input password
    } else if(key == '#') {
      if(input_password == password_2) {
        Serial.println("password is correct");

     digitalWrite(MOTOR_PIN1, HIGH);
     digitalWrite(MOTOR_PIN2, LOW);
     delay (3000);

      } else {
        Serial.println("password is incorrect, try again");
      }

      input_password = ""; // reset the input password
    } else {
      input_password += key; // append new character to input password string
    }
  }
}

what's your question?

the keyboard code should not be part of the LED code, or part of the motor code ... the keyboard code should be completely separate ... it should simply update the value of a variable depending on which code is entered ... the motor code and led code should simply monitor the value of the variable and run accordingly

In this program, the functions loop_RGB() and loop_DCMOTOR() are
taking turns to try to read the password. If you hit # after typing
the password for the LED, and loop_DCMOTOR() happens to to read your
key press, it will tell you the password is wrong, and reset what you
have typed.
As already stated in a comment and an answer, the solution is to read
the keypad in only one place. You could write a dedicated function for
this, but I would instead just put this code in loop:
void loop() {
    char key = keypad.getKey();

    if (key) {
        Serial.print("key pressed: ");
        Serial.println(key);
        if (key == '*') {  // '*' means reset the input
            input_password = "";
        } else if (key == '#') {  // '#' means validate the input
            if (input_password == password_1) {
                Serial.println("Corect RGB LED password.");
                actuate_LED();
            } else if (input_password == password_2) {
                Serial.println("Corect motor password.");
                actuate_motor();
            } else {
                Serial.println("Incorrect password.");
            }
            input_password = "";  // reset the input
        } else {
            input_password += key;  // append new character
        }
    }
}

Here, actuate_LED() and actuate_motor() are supposed to be small
functions that do the device actuation and nothing more. They do not
concern themselves with the keypad or a password.

write 3 functions, one to receive the password, one to run the DC motor, one to drive the LED. Now in the function to receive the password use an array of 4 bytes to store the password and the 'x' button to clear the array. The function should run a for loop to receive all the 4 digits and the "x" key should break the loop and clear out the array.
You can write the RGB and Motor driver function as per your needs.
In the main loop, you should receive the password and then process this password to run the RGB or motor using a if-else condition.
For any further query feel free to clarify.


text:
How to create 2 individual daisy chains using the MAX7219 Module and Mega2560
I am using MAX7219 8 digit 7 segment displays with Arduino Mega2560. Now, I have to physically space out the displays far from each other. Hence, after a certain distance the displays on the far end start flickering. So, can we setup 2 individual daisy chains using the MAX7219 module with Arduino Mega2560.
Thanks for helping out in advance.


text:
Hysteresis and scaling range
Here I asked about how to add an hysteresis on ADC readings. The answer received was very good and it worked out of the box.
Still I'm having troubles trying to generalize the resample function in order to map the input values to a different range of output values, where the lower rail is not zero.
If the lower rail was zero, it would be enough to change the shifts with a multiplication/division for 1024 / max. But I cannot understand how to handle the lower rail when min > 0.
My attempt:
int Menu::resample(int adc, int *value, byte min, byte max)
{
    // sanity checks omitted: min < max and max < 128

    double m = 1015.0 / (max - min); // 1015 = 1023 - 8 (1 LSB of low-res output)
                                     // otherwise it reaches 126 even if max = 127
    int q = min << 3;

    int lowerTest = (q + *value * m) - ADC_HYSTERESIS;
    int higherTest = (q + (*value + 1) * m) + ADC_HYSTERESIS;

    int lowerOutput = min + (adc + ADC_HYSTERESIS) / m;
    int higherOutput = min + (adc - ADC_HYSTERESIS) / m;

    if (adc < lowerTest) *value = lowerOutput;
    else if (adc >= higherTest) *value = higherOutput;

    if (*value > max) *value = max;
    if (*value < min) *value = min;
    return *value;
}

There is something wrong in my math, since the comparison always falls under the first if (i.e. *value = lowerOutput).
May you help me to fix this code so I can have an hysteresis on any scaled output?
Note: instead of using a static variable for value as in the answer, I use a struct:
slider.value = resample(adc, &slider.lastValue, slider.min, slider.max);

where:
typedef struct
{
    int value;
    int lastValue;
    int min;
    int max;
} slider_t;

slider_t slider;

First, a couple of comments about this first attempt.
There is no point in storing in slider_t both lastValue and value.
The way this is used, both fields are always updated with the same
value: lastValue is updated by pointer inside resample(), while
value is updated by assigning it the value returned by resample(). I
would suggest removing the field lastValue and either:

providing value by value (rather than by pointer) to resample(),
or

providing a reference to a slider_t as the only parameter.

The first approach is better if you want to avoid resample() and
slider_t being tightly coupled.
Next, there is a mix between int and byte types. If you want to save
memory, and improve consistency, I would use byte for all low-res
values living in the output domain of resample(). Actually, I would
use uint8_t, which is the same, only more standard.
Then, there are a few things I do not understand in this code:

Why 1015? It seems to me this number should be dependent on the
width of output range.

Why min << 3? Again, this is a division by 8, while the proper
factor should be probably be output-range dependent.

Now, for the solution, I would try this approach:

Compute the minimum and maximum possible output values consistent with
the provided input, accounting for the hysteresis.

Constrain the output to remain within this bracket.

In code:
uint8_t Menu::resample(int adc, uint8_t value, uint8_t min, uint8_t max)
{
    value = constrain(value, min, max);  // just in case...
    uint8_t lower = map(adc - ADC_HYSTERESIS, 0, 1024, min, max+1);
    uint8_t upper = map(adc + ADC_HYSTERESIS, 0, 1024, min, max+1);
    return constrain(value, lower, upper);
}

Some points worth noticing:

I do not know whether this was originally intended, but the Arduino
function map(x, in_min, in_max, out_min, out_max) does a poor job
at mapping the interval [in_min, in_max] to [out_min,
out_max]. It does, however, do a good job at mapping [in_min,
in_max) to [out_min, out_max) (mind the semi-open intervals).
This is why the four last parameters of the call to map() are (0,
1024, min, max+1), rather than (0, 1023, min, max).

The first call to constrain() can be removed if the caller bears
the responsibility of guaranteeing this precondition.

If the precondition is valid (or, like here, enforced), it will also
hold for the returned value, provided adc is within [0, 1024).

This method would be called like this:
slider.value = resample(adc, slider.value, slider.min, slider.max);

It's unbelievable how a quite complex task can be solved with few lines of code. I'm impressed. Thank you!


text:
ESP8266 + NodeMCU Motor Shield spinning motor only in one direction
I hooked my ESP8266 Wi-Fi module to an ESP-12E Motor Shield and connected it to an RC car. It works fine when connected to my laptop (Goes forward, backward, left, and right. Though the car doesn't seem to turn a lot because of low power). I connected it to a 7.4v power supply, and it works fine, except it only moves forward and only turns right. Doesn't turn the motors the other direction.
I followed this tutorial. In case, you'd want the code.
I did have a change of code though, this is the only code I changed
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

// These are the pins used to control the motor shield

#define STEER_MOTOR_POWER D2 // Motor A
#define STEER_MOTOR_DIRECTION D3

#define DRIVE_MOTOR_POWER D1 // Motor B
#define DRIVE_MOTOR_DIRECTION D4

int drivePower = 1000;

uint8_t driveDirection = LOW;

int steeringPower = 1000;

uint8_t steerDirection = LOW;

// ----------------
// Set your WiFi SSID and Password here
// ----------------
const char* ssid = "xxxxx";
const char* password = "xxxxxxxxxxx";

ESP8266WebServer server(80);

void setup(void){

  pinMode(DRIVE_MOTOR_POWER, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
  pinMode(DRIVE_MOTOR_DIRECTION, OUTPUT);
  pinMode(STEER_MOTOR_POWER, OUTPUT);
  pinMode(STEER_MOTOR_DIRECTION, OUTPUT);

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

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

  if (MDNS.begin("WifiCar")) {
      Serial.println("MDNS Responder Started");
      analogWrite(DRIVE_MOTOR_POWER, 10);
      digitalWrite(DRIVE_MOTOR_DIRECTION, driveDirection);
      delay(2000);
      analogWrite(DRIVE_MOTOR_POWER, 0);
  }

    server.on("/car/controls/front", [](){
      Serial.println("front");
      analogWrite(DRIVE_MOTOR_POWER, drivePower);
      digitalWrite(DRIVE_MOTOR_DIRECTION, driveDirection);
      delay(100);
      server.send(200, "text/plain", "front");
    });

    server.on("/car/controls/back", [](){
      Serial.println("back");
      analogWrite(DRIVE_MOTOR_POWER, drivePower);
      digitalWrite(DRIVE_MOTOR_DIRECTION, !driveDirection);
      delay(100);
      server.send(200, "text/plain", "back");
    });

    server.on("/car/controls/stopDirection", [](){
      delay(100);
      Serial.println("stopDirection");
      analogWrite(DRIVE_MOTOR_POWER, 0);
      delay(100);
      server.send(200, "text/plain", "stopDirection");
    });

    server.on("/car/controls/right", [](){
      Serial.println("right");
      analogWrite(STEER_MOTOR_POWER, steeringPower);
      digitalWrite(STEER_MOTOR_DIRECTION, steerDirection);
      delay(100);
      server.send(200, "text/plain", "right");
    });

    server.on("/car/controls/left", [](){
      Serial.println("left");
      analogWrite(STEER_MOTOR_POWER, steeringPower);
      digitalWrite(STEER_MOTOR_DIRECTION, !steerDirection);
      delay(100);
      server.send(200, "text/plain", "left");
    });

    server.on("/car/controls/stopSteering", [](){
      delay(100);
      Serial.println("stopSteering");
      analogWrite(STEER_MOTOR_POWER, 0);
      delay(100);
      server.send(200, "text/plain", "stopSteering");
    });

  server.begin();
  Serial.println("HTTP Server Started");
}

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

Done! Thank you!

maybe you did not make the correct connections

The connections are good. It works okay when connected to my laptop (though its very slow and it barely moves but you know there's a reaction).
my batteries are connected exactly as the tutorial mentioned (VIN and GND) while the VIN and VM shortcut both connected together.

reduce your code to minimum ... write a sketch that moves one motor in only one direction  stops, moves motor in other direction, stops and repeats


text:
What are the Vs and Vss pins on an L293D chip for?
I made a simple test circuit to help me understand the L293D H-bridge that comes with the Arduino starter kit.

Digital output pins of the Arduino are wired to the input pins on the H-bridge. Arduino code alternately sends 1/0 and 0/1 down those two output pins, basically (as I understand it) creating an extremely low frequency alternating current in the two output pins on the H bridge. Two LEDs are wired in parallel to the output pins, in opposite directions, so they flash, demonstrating the alternating nature of the current.
The project I'm working on from the starter kit right now is the Zoetrope (page 102), and in that project the L293D is used to control a motor. The Arduino's 5V is connected to Vss and a 9V battery is connected to Vs.
So I'm a little surprised that I got it to work without using the Vs and Vss pins at all. What are they for? I did try swapping the LEDs out for the motor and it doesn't work (not enough power, I guess). But if I hook the 5V on the Arduino up to the Vs pin, it does! Hooking the 5V up to only the Vss pin, however, is not enough to power the motor.
So I sort of get the idea that without Vs and Vss current, the current from the input pins is enough to light the LEDs, but what I don't understand is:

If the voltage on the input pins isn't enough to drive the motor, how come connecting the 5V to the Vs pin is? It's the same voltage as is on the input pins.

What is the Vss pin for?

As you can see in the linked L293D PDF
VS is Supply Voltage (here connect the power source for motor)
VSS is Logic Supply Voltage (here connect the power source for the L293D chip logic - usually the same source as for +5V for Arduino)

The VSS suplies energy for the L293D to work correctly (like the Enable pin, inputs and such)

Also as you can see on the BLOCK DIAGRAM there are some mysterious diodes connected in little unusual way - at least on first look. When everything is well powered and normal, there are closed and do not conduct any current.
But if the voltage on (say) OUT1 became negative, then the lower diode connected to ground would start lead current and pull the OUT1 to the ground.
Similary if the voltage on OUT1 became higher, then the VS power source, then the top diode would open and drag the OUT1 down to the VS voltage.
It is for secure the internal circuits to work in sane environment. And if there is a motor (if any other inductance as relay or so), then there will be such peaks.
Similar security diodes are probably also on all input pins. (It is usual in logical circuits to limit input voltage in such way.) As you did not connect the VS to any power, when you send +5V (logical one) to any input pin, it was "pulled down" to VS via some such diode. This effectively "pulled up" the VS near the voltage on the pin and with VS powered the internal logic of L293D begin work, so magic happened.

There may be even some similary secured connection between VS and VSS, so some power from your Arduino output pin leaked by long and non-planed way to your LEDs and made them shine. LEDs do not need much current.

When you connected the motor instead, the long way proved to be too long and to have too much rezistence along it, that (nearly) all the voltage was distributed along it and on the motor was nearly nothing - and nearly no current was able go thru. Which is luck, as Arduino output pins have limit of 20 mA of current (or so).
When you conected +5V on the VS pin, there is much shorter way from it to motor and also with a lot less resistance along it, so there was enought voltage and enought current for the motor, so it was able to run.
Try it and measure the resistence of your motor - you will see, it will be nearly nothing, compared to the R=220 you used with the LEDs.
While it may not be visible in such simple example like this, you really should power the VSS so the logic there would work reliable.


text:
How can I access ESP32-CAM from outside local network other than port forwarding?
I have a ESP32-CAM AIThinker which I have programmed using Arduino IDE to stream video.  I have another board ESP8266-12e that I am using on a MQTT system that turns on and off the ESP32 as well as sending it the Name and password of my local network to sign in.  When the ESP32-CAM is on and streaming I can access it on my local network and by port forwarding in my Router I can sign in and view it from anywhere.  I have built a Mac and Android app which will access and stream the ESP32 displaying it inside the app.
I would rather NOT port forward my router.  Is there a way to add some code to the ESP32 so that I could use Apple TV, or the Android equivalent, or HomeKit, to open the port associated with the ESP32 so it can be accessed outside my local network?  Port forward is not real secure and I would like to avoid it if possible.
I have added some code to try to POST the jpg-stream to my WIX website where I added a page with an image.  However even though the website got the POST and it was valid I received a response code 403 FORBIDDEN this is the full response.
10:25:03.026 -> 403
10:25:03.026 ->
10:25:03.026 -> <title>403 Forbidden</title>
10:25:03.026 ->
10:25:03.026 ->
403 Forbidden

10:25:03.026 ->
nginx
10:25:03.026 ->
10:25:03.026 ->

Here is the code currently running on the ESP32-CAM;
#include "src/OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <time.h>
#include "FS.h"                // SD Card ESP32
#include "SD_MMC.h"            // SD Card ESP32
#include <WiFiClient.h>
#include <EEPROM.h>
#include <string.h>
#include <stdio.h>
//ADDED FOR POST
#include <HTTPClient.h>

int know;
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
//for reconnect
unsigned long previousMillis = 0;
unsigned long interval = 30000;
//stuff to bring in string
const byte numChars = 100;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
// variables to hold the parsed data
char messageFromPC[numChars] = {0};
float floatFromPC = 0;
char ssidString[numChars] = {0};
float floatFromPC2 = 0;
char pskString[numChars] = {0};
char IP[numChars] = {0};
char zone[numChars] = {0};
char myChar[numChars]= {0};
char myChar2[numChars]= {0};
char myChar3[numChars]= {0};
char myChar4[numChars]= {0};
boolean newData = false;
//end stuff ti bring in string
String f;
int addr = 0;
OV2640 cam;

WebServer server(XX);

const char HEADER[] = "HTTP/1.1 200 OK\r\n" \
                      "Access-Control-Allow-Origin: *\r\n" \
                      "Content-Type: multipart/x-mixed-replace; boundary=123456789000000000000987654321\r\n";
const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n";
const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: ";
const int hdrLen = strlen(HEADER);
const int bdrLen = strlen(BOUNDARY);
const int cntLen = strlen(CTNTTYPE);

void handle_jpg_stream(void)
{
  char buf[32];
  int s;

  WiFiClient client = server.client();

  client.write(HEADER, hdrLen);
  client.write(BOUNDARY, bdrLen);

  while (true)
  {
    if (!client.connected()) break;
    cam.run();
    s = cam.getSize();
    client.write(CTNTTYPE, cntLen);
    sprintf( buf, "%d\r\n\r\n", s );
    client.write(buf, strlen(buf));
    client.write((char *)cam.getfb(), s);
    client.write(BOUNDARY, bdrLen);
  }
}

const char JHEADER[] = "HTTP/1.1 200 OK\r\n" \
                       "Content-disposition: inline; filename=capture.jpg\r\n" \
                       "Content-type: image/jpeg\r\n\r\n";
const int jhdLen = strlen(JHEADER);

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

  cam.run();
  if (!client.connected()) return;

  client.write(JHEADER, jhdLen);
  client.write((char *)cam.getfb(), cam.getSize());

}

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

void setup()
{

  Serial.begin(57600);
  Serial.print("setup");

delay(10000);

//RESET EEPROM COMMENT OUT
if(Serial.available()){
delay(2000);

  recvWithStartEndMarkers();

    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}
//TO HERE
    delay(10000);
    Serial.print("network");
    Serial.print(ssidString);
    Serial.print("pass");
    Serial.print(pskString);
    Serial.print("time zone");
    Serial.print(zone);

if(ssidString[0] != '\0'){
 EEPROM.begin(512);  //Initialize EEPROM

  // write appropriate byte of the EEPROM.
  // these values will remain there when the board is
  // turned off.

 EEPROM.write(addr, 'A');    //Write character A
  addr++;                      //Increment address
  EEPROM.write(addr, 'B');    //Write character B
  addr++;                      //Increment address
  EEPROM.write(addr, 'C');    //Write character C

  //Write string to eeprom

  //RESET EEPROM SWITCH THESE TWO
 String www =  ssidString +String(",") + String(pskString) + String(",")+String(zone)+String(",");
 //String www =  newString +String(",") + String(oldString) + String(",")+String(zoneString)+String(",");
  Serial.print (www);

for(int i=0;i<www.length();i++) //loop upto string lenght www.length() returns length of string
  {
    EEPROM.write(0x0F+i,www[i]); //Write one by one with starting address of 0x0F
  }

  EEPROM.commit();
  //Read string from eeprom           //Increment address
  //COMMENT OUT NEXT BRACKET RESET EEPROM
}
//RESET EEPROM COMMENT OUT NEXT SECTION
else if(ssidString[0] == '\0'){
   EEPROM.begin(512);
    Serial.println("WHAT"); //Goto next line, as ESP sends some garbage when you reset it
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x00
  addr++;                      //Increment address
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x01
  addr++;                      //Increment address
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x02
  addr++;   //Increment address
  Serial.print(char(EEPROM.read(addr)));    //Read from address 0x03

  //Read string from eeprom
  String www;
  //Here we dont know how many bytes to read it is better practice to use some terminating character
  //Lets do it manually www.circuits4you.com  total length is 20 characters
  for(int i=0;i<100;i++)
  {
    www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
  }

 Serial.println("this");
  Serial.print(www);  //Print the text on serial monitor

  www.toCharArray(myChar,100);
    char * token = strtok(myChar,",");
    char * token2 = strtok(NULL,",");
    char * token3 = strtok(NULL,",");

Serial.println("one");
 Serial.print(token);
 Serial.println("two");
 Serial.print(token2);
 Serial.println("three");
 Serial.print(token3);

strcpy(myChar2,token);
strcpy(myChar3,token2);
strcpy(myChar4,token3);

//RESET EEPROM COMMENT OUT TO HERE
}

#define SSID1 ssidString
#define PWD1 pskString

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  // Frame parameters
  //  config.frame_size = FRAMESIZE_UXGA;
  config.frame_size = FRAMESIZE_VGA;
  config.jpeg_quality = 12;
  config.fb_count = 2;

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

  cam.init(config);

  IPAddress ip;

  WiFi.mode(WIFI_STA);
  if(ssidString[0] != '\0'){
   // digitalWrite(33,LOW);
  WiFi.begin(ssidString, pskString);
  Serial.println("zone");
  Serial.print(zone);
 know = atoi(zone);
  }
  else if(ssidString[0] == '\0'){
     WiFi.begin(myChar2, myChar3);
     Serial.println("myChar4");
      know = atoi(myChar4);
     Serial.print(myChar4);
  }

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }
  String rrr = String("/") + String(zone) + String("/") + String ("1");
  Serial.print("rrr");
  Serial.println(rrr);
  ip = WiFi.localIP();
  Serial.println(F("WiFi connected"));
  Serial.println("");
  Serial.println(ip);
  Serial.print("Stream Link: http://");
  Serial.print(ip);
  Serial.println(rrr);//userName
  server.on(String(rrr), HTTP_GET, handle_jpg_stream);
  server.on("/jpg", HTTP_GET, handle_jpg);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.print("loop");

delay(1000);

}

void loop()
{

 if (WiFi.status() == WL_DISCONNECTED){

  if(ssidString[0] != '\0'){

  WiFi.begin(ssidString, pskString);
  Serial.println("zone");
  Serial.print(zone);
 know = atoi(zone);
  }
  else if(ssidString[0] == '\0'){
     WiFi.begin(myChar2, myChar3);
     Serial.println("myChar4");
      know = atoi(myChar4);
     Serial.print(myChar4);
  }
   while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }}
  unsigned long currentMillis = millis();

  if((WiFi.status()!= WL_CONNECTED) & (currentMillis-previousMillis >= interval)){
    Serial.print(millis());
    WiFi.disconnect();
    WiFi.reconnect();
    previousMillis = currentMillis;
  }
 else if (WiFi.status() == WL_CONNECTED){

//THIS IS THE CODE I ADDED TRYING TO POST VIDEO
HTTPClient http;
  http.begin ("https://www.creatucate.com/video-1");
  http.addHeader("Content-Type","image/jpeg");

  int httpResponseCode = http.POST("POSTING from ESP32");

  if(httpResponseCode>0){
    String response = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(response);
  }
  else{
    Serial.print("Error on sending POST: ");
    Serial.println(httpResponseCode);
  }

//END NEW CODE
server.handleClient();

}}
    //more new stuff for string
    void recvWithStartEndMarkers() {
        static boolean recvInProgress = false;
        static byte ndx = 0;
        char startMarker = '<';
        char endMarker = '>';
        char rc;

        while (Serial.available() > 0 && newData == false) {
            rc = Serial.read();

            if (recvInProgress == true) {
                if (rc != endMarker) {
                    receivedChars[ndx] = rc;
                    ndx++;
                    if (ndx >= numChars) {
                        ndx = numChars - 1;
                    }
                }
                else {
                    receivedChars[ndx] = '\0'; // terminate the string
                    recvInProgress = false;
                    ndx = 0;
                    newData = true;
                }
            }

            else if (rc == startMarker) {
                recvInProgress = true;
            }
        }
    }

    //============
    //RESET EEPROM COMMENT OUT ALL THE REST
    void parseData() {      // split the data into its parts

        char * strtokIndx; // this is used by strtok() as an index

        strtokIndx = strtok(tempChars,",");      // get the first part - the string
        strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

        strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
        strcpy(ssidString,strtokIndx);

        strtokIndx = strtok(NULL, ",");
        strcpy(pskString,strtokIndx);
        strtokIndx = strtok(NULL, ",");
        strcpy(zone,strtokIndx);

    }

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

    void showParsedData() {
        Serial.print("Message ");
        Serial.println(messageFromPC);
        Serial.print("water level ");
        Serial.println(floatFromPC);
        Serial.println(ssidString);
        Serial.print("battery level ");
        Serial.println(floatFromPC2);
        Serial.println(pskString);
        Serial.print("time zone is ");
       Serial.println(zone);

    }

If this is not the correct place for this question please advise me.  I am not even sure this can be done but I hope so.

you can push the frame data to a web-based WebSocket server, which you can connect to your app w/o port configs. You could also do that with a web-based http server for that matter; POST the image to the server, GET it from the app.

I have changed my original post to include code to POST to a http server and the response from the server.  The request contained valid data and was understood by the server, but the server is refusing action.  I am trying to post to WIX.  Could you give me some more guidance?


text:
Problem changing the state of the blue LED on an ESP8266
I am trying to change the blue LED on my ESP8266. I can do this (sort of...)
In the setupWifi() function below, there is a loop that is supposed to rapidly blink the LED while wifi is connecting.  The only way I can flash the blue light is if the print statement (Serial.print(".");) is present.  If I remove this (and even increase the delay) the blue light will not flash.  If the print statement is present, it works as expected.
The other issue I have is when I click the web page to turn the light on or off.  The values print correctly, but the LED only blinks briefly on in both cases.
My questions are:

Why am I only able to change the led when there is a print statement in the loop while waiting for wifi connectivity?
Why am I unable to change the led in the main loop?

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <SoftwareSerial.h>

#define SECONDS_PER_MINUTE 60
#define SECONDS_PER_HOUR 60 * SECONDS_PER_MINUTE
#define SECONDS_PER_DAY 24 * SECONDS_PER_HOUR
#define SECONDS_PER_WEEK 7 * SECONDS_PER_DAY

#define LED_PIN 1
#define TIME_UPDATE SECONDS_PER_WEEK

const char* ssid = "ssid";
const char* password = "password";
const char* hostname = "hostname";

const long utcOffsetInSeconds = -4 * SECONDS_PER_HOUR;

SoftwareSerial ESPserial(2, 3); // RX | TX
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
ESP8266WebServer server(80);

uint8_t ledStatus = LOW;
uint8_t lastLedStatus = ledStatus;
unsigned long lastUpdate = 0;

void updateTime() {
  time_t epochTime = timeClient.getEpochTime();

  if (epochTime > lastUpdate + TIME_UPDATE) {
    Serial.println("Syncing time with server");
    timeClient.update();
    time_t epochTime = timeClient.getEpochTime();
    struct tm *ptm = gmtime ((time_t *)&epochTime);

    int hour = timeClient.getHours();
    int minute = timeClient.getMinutes();
    int second = timeClient.getSeconds();
    int day = ptm->tm_mday;
    int month = ptm->tm_mon+1;
    int year = ptm->tm_year+1900;

    Serial.printf("Time synched at: %d/%d/%d %d:%d:%d\n", day, month, year, hour, minute, second);
    lastUpdate = epochTime;
  }
}

void setupSerial() {
  Serial.begin(9600);
  ESPserial.begin(115200);
  ESPserial.println("AT+IPR=9600");
  delay(1000);
  ESPserial.end();
  ESPserial.begin(9600);
  Serial.println("Serial Port Initialized");
  ESPserial.println("AT+GMR");
}

void setupWifi() {
  bool ledState = HIGH;
  Serial.println("Connecting to WIFI");

  WiFi.mode(WIFI_STA);
  WiFi.hostname(hostname);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
    digitalWrite(LED_PIN, ledState);
    ledState = !ledState;
  }

  Serial.println("WIFI connected");
  Serial.println(WiFi.localIP());
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  timeClient.begin();
  setupSerial();
  setupWifi();
  delay(100);

  server.on("/", handleOnConnect);
  server.on("/led1on", handleLedOn);
  server.on("/led1off", handleLedOff);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

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

  if (lastLedStatus != ledStatus) {
    Serial.printf("Writing %u\n", ledStatus);
    digitalWrite(LED_PIN, ledStatus);
    lastLedStatus = ledStatus;
  }
}

void handleOnConnect()  {
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handleLedOn() {
  ledStatus = HIGH;
  Serial.printf("Turning LED: %u\n", ledStatus);
  // digitalWrite(LED_PIN, ledStatus);
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handleLedOff() {
  ledStatus = LOW;
  Serial.printf("Turning LED: %u\n", ledStatus);
  // digitalWrite(LED_PIN, ledStatus);
  server.send(200, "text/html", SendHTML(ledStatus));
}

void handleNotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(uint8_t ledStatus){
  String ptr = "<!DOCTYPE html> \n";
  ptr +="<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="\n";
  ptr +="\n";
  ptr +="\n";
  ptr +="
ESP8266 Web Server
\n";
  ptr +="
Using Access Point(AP) Mode
\n";

   if(ledStatus
  )
  {ptr +="
LED1 Status: ON
OFF\n";}
  else
  {ptr +="
LED1 Status: OFF
ON\n";}

  ptr +="\n";
  ptr +="\n";
  return ptr;
}

what do you want to know?

Why does the first case require a println and why doesn't the second case turn the led on and off at all (other than a brief flash when turning it on or off - which could even be the webserver)

your question belongs in your post, not is a comment ... this site is not a forum where you chat back and forth ... all of your question should be in one place

Do you know for sure that the LED is meant to be controllable? Pin 1 is the serial transmit pin, so I’d guess that the LED is really meant to indicate activity on the serial port.

I have read that changing it is possible and have been successful at doing so under the right conditions.  Your question is very valid and I didn't realize that they shared the same pin.  I'll give this a shot with an external LED, but I was hoping to use the built-in one for diagnostics :-/

calling Serial.print changes the pin_mode of pin1 to special. if you call pinMode before digitalWrite (or don't call print) it will work each time.


text:
Pin outping 1V instead of expected 5V, not hardware related
Heyo everyone !
I'm in a project where I need to send a signal if I detect vaccuum.
I'm sending the signal on PIN 9 but I soon realized that I was only getting 1V.
Tought I was alternating between signal/no_signal but the log provided me with constant and consistent values.
Then I started doubting about my board so I made PIN 10 always output. Under the same load as PIN 9 (I switch the cable connecting from PIN 9 to the circuit, to PIN 10 to the circuit ), I get a good 5V. Thus, I exclude any load problem.
Regarding the PIN output issue, you can all see that it's not missing.
My last hypothesis is that there's some sort of sorcery with my code that I don't know and couln't find on the internet...
Any idea on what might be going on ?
// Constant
const int BL1 = 9;// BINARY LED 1 pin
const int TEST = 10;// BINARY LED 1 pin
const int AP = A0;// ANALOG PRESSOSTAT pin
const int P = 85;// TRIGGER PRESSURE value

// Variables
int LS1 = LOW;  // LED 1 STATE
float RPV = 1; // Raw Pressostat Voltage (0-1024)
float PV = 1; // Pressostat Voltage (V)
float PDP = 20; // Pressostat Deduced Pressure (kPa)

// Initialization of pins at startup
void setup() {
  pinMode(AP, INPUT); // ANALOG PRESSOSTAT pin set as INPUT
  pinMode(BL1, OUTPUT);// BINARY LED 1 pin set as OUTPUT
  pinMode(TEST, OUTPUT);// BINARY LED 1 pin set as OUTPUT
  pinMode(LED_BUILTIN, OUTPUT);// LED_BUILTIN pin set as OUTPUT
  Serial.begin(9600);
}

void loop() {
    digitalWrite(TEST, HIGH);
    RPV = analogRead(AP);
    PV = (RPV/1024)*5;
    PDP = (-1)*(PV-1)*(-101/4);
    Serial.print("Pression: ");
    Serial.print(PDP);
    if ( PDP > P ){
      int LS1 = HIGH;  // LED 1 STATE
      digitalWrite(BL1, HIGH);
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.print(" | LED: 1");
      }
    else {
      int LS1 = LOW;  // LED 1 STATE
      digitalWrite(BL1, LOW);
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print(" | LED: 0");
    }
    digitalWrite(BL1, LS1);
    Serial.print(" | Trigger: ");
    Serial.println(P);

  }

What device is connected to the output pin? How much current does it draw from the pin?

How are you measuring the voltage on pin 9 ? A digital multimeter will tend to integrate and give you an average reading so say 5 volts at a 20% duty cycle will be measured as 1 volt. An oscilloscope, on the other hand, will show a true voltage for the complete waveform.

@6v6gt That's what I (think I) eliminated with my second paragraph. Due to the size of the entiere project (it's only a small part of it), I can't use an oscilloscope...

I don't know but the "always on" pin can hold it... So that's not the issue

@6v6gt UPDATE: I found an oscilloscope that I can use, I'll update you ASAP. Anyway, how, with my code, could I send a HIGH signal 20% of the cycle ?

It is the 20% per cycle thing happening: How does that is happening ?!

Local variable declarations -- See @kiiv's answer: https://arduino.stackexchange.com/a/93195/6628

add a delay(999) to the loop and re-check your multimeter, might not be the steady HIGH you expect.

Here's a working script (I went back to PWM pin, if that matter at all)
void loop() {
  ...// unrelated code
  if (PDP > P) {
    LS1 = HIGH;                               // LED 1 HIGH
    digitalWrite(BL1, LS1);
    digitalWrite(LED_BUILTIN, LS1);
    Serial.print(LS1);
  }
  else {
    LS1 = LOW;                                // LED 1 STATE
    digitalWrite(BL1, LS1);
    digitalWrite(LED_BUILTIN, LS1);
    Serial.print(LS1);
  }
  ...// more unrelated code
}

I'll reduce it a little
void loop() {
    // ... doesn't matter
    if ( PDP > P ){
      int LS1 = HIGH;            // shadows global variable (creates local variable that won't exist after })
      digitalWrite(BL1, HIGH);
    } else {
      int LS1 = LOW;             // again shadows global variable
      digitalWrite(BL1, LOW);
    }
    digitalWrite(BL1, LS1);      // LS1 is still LOW

  }

Mistery solved

Yep, the local variables don't persist outside their scope {}, so the global variable with the same name remains unchanged outside of those scopes.  It could seem like PWM because the internal variables could toggle the pin.

Oh god, how didn't I realized that ?!
Thank you for you enlightening answer ! That's why even my own answer (which was to change to a non PWM pin) revealed itself to not work...


text:
MacOS Ventura freezes/crashes when i plug in my Arduino Nano Clone
I'm using a MacBook Pro 2013 Late with OpenCore Patcher. Currently Ventura 13.3.1 is installed. Before this version was installed, I had no problem using arduino on my MacOS computer. But right now, when I plug in my Arduino Nano Clone, the computer suddenly freezes and does not respond to any interaction. I have to press and hold the power button to restart the computer.
I tried to plug in another board called NodeMCU which has CH340 chip likewise I did with the arduino, same trouble happened again. So at that point I was guessing it was a CH340 driver problem or something about it. To test my theory, I plugged in my Raspberry Pi Pico and it worked perfectly. So it's probably CH340 chip problem but I could not find any solution in web. May there is a system integrity problem with OpenCore which the version is not compatible with the current operation system version.
If anyone can help me with this issue I'd be really appreciated, since I have a project which must be completed within 3 weeks.

Have a look at this: https://github.com/adrianmihalko/ch340g-ch34g-ch34x-mac-os-x-driver , and this: https://learn.sparkfun.com/tutorials/how-to-install-ch340-drivers/all#mac-osx

Clone Arduino has a history of doing that. Check here:
https://forum.arduino.cc/t/macbook-keeps-crashing-when-i-plug-in-ch340-arduino/440584