# Question
Title: 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
    }

```

# Answer
* 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.
> 1 votes

# Answer
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.
> 0 votes

---
Tags: arduino-mega, relay
---


# Question
Title: 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
    }
  }
}

```

# Answer
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.
> 2 votes

# Answer
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.
> -1 votes

---
Tags: arduino-uno
---


# Question
Title: 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();
}

```

# Answer
> 1 votes
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.

---
Tags: pwm, voltage, input
---


title: Hysteresis and scaling range

text:
# Question
Title: 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;

```

# Answer
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:

1. providing `value` by value (rather than by pointer) to `resample()`, or
2. 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:

1. 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).
2. The first call to `constrain()` can be removed if the caller bears the responsibility of guaranteeing this precondition.
3. 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);

```
> 2 votes

---
Tags: adc, mathematics, filter
---


# Question
Title: 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:

1. 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.
2. What is the Vss pin for?

# Answer
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)

2. 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.

1. 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.
> 1 votes

---
Tags: arduino-uno, h-bridge, l293d
---


title: interface pcf7991at to arduino

text:
# Question
Title: interface pcf7991at to arduino
I wanted to try to interface the pcf7991at with arduino, I assembled the pcb containing the pcf7991at following the diagram shown in the datasheet. I saw that a frequency of 125khz must go on the CLK pin of the pcf, so I ask you if it is possible to use an internal arduino timer to try to see if the pcf7991at works.

# Answer
> 1 votes
The communication between MCU (Arduino) and IC (PCF7991AT) can work at any frequency (like SPI or I2C). The 125khz antenna frequency is generated in the IC internally. But you need to set the divider of the clock source (your crystal hooked up to the IC)

https://datasheet.lcsc.com/lcsc/2208260930\_NXP-Semicon-PCF7991AT-1081-M\_C5143533.pdf

See page 7 -\> 8.4 short explanation page 13 -\> to set the register

Hope this helps!

# Answer
> 0 votes
The Arduino is indeed capable of generating a 125kHz signal. This example generates a 125kHz signal (50% duty cycle) on digital pin 3 of an Arduino Uno/Nano using Timer 2.

```
const int pulsePin = 3;  // note OC2B Pin D3 ! ! !
volatile uint32_t pulseCount = 0;

void setup(){

  pinMode(pulsePin, OUTPUT);

  cli() ;
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2 = 0;
  OCR2A = 127 ; // f =  125kHz @16MHz clock
  OCR2B = (float) OCR2A * 0.5 ;
  TCCR2A |= (1 << WGM21) | (1 << WGM20) | (1 << COM2B1 ) ; // Mode 7 (fast PWM )
  TCCR2B |= (1 << CS20) | (1 << WGM22) ;   // ps /1  mode 7
  sei() ;
}

void loop() {
}

```

---
Tags: arduino-uno, atmega328
---


# Question
Title: 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);

  }

```

# Answer
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
}

```
> 0 votes

# Answer
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
> 3 votes

---
Tags: arduino-mega, voltage-level, code-review
---


# Question
Title: Reducing read time for reading DS18B20 temp sensors
I have a number of temperature sensors connected up to an Arduino - I've split it into 3 sections, with each section having a 2-4 sensors on it (due to distances). This works, but the code I'm using would seem to me to be very inefficient - particularly with respect of how long it takes to read all the sensors.

I've got 3 code blocks one after each other (which are modified from some code online) which look as below - save, of-course, for the name of the 1wire class.

```
// Dallas 1 Wire (Main Area):

 //  ds.reset_search();
 //  delay(250);
  while (ds.search(addr))
  {
    for( i = 0; i < 8; i++) {
      Serial.print(addr[i], HEX);
    }

    if (OneWire::crc8(addr, 7) != addr[7]) {
        Serial.println("CRC is not valid!");
        return;
    }

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 0);        // start conversion, with parasite power on at the end

    delay(1000);     // maybe 750ms is enough, maybe not
    // we might do a ds.depower() here, but the reset will take care of it.

    present = ds.reset();
    ds.select(addr);
    ds.write(0xBE);         // Read Scratchpad

    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
    }
    raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
    }
    celsius = (float)raw / 16.0;
    Serial.print(":");
    Serial.print(celsius);
    Serial.print(",");
  }

```

I note that there is a 1000ms delay after each sensor is read, and I'm wondering if I can reduce this to a single 750ms delay for all the sensors. My initial attempts to do this did not meet with success - but I confess that I can't quite get my head around the ds.reset, ds.select etc - and my initial attempts to do this have all failed.

Is it possible to remove this delay after reading each sensor ?

# Answer
After nearly a year and a number of experiments later, I've learned a little bit more about using these devices:

Issuing the sensors a Skip ROM command followed by Convert T command starts all devices converting temperature at once (pg.11 of the datasheet). Then you need only wait one delay period of {750,375,188,94}ms for a {12,11,10,9}-bit conversion, respectively, before you can start reading back the temperatures.

If the devices are being powered parasitically, the bus will need a strong pullup during the conversion; the 4.7KOhm pullup is not sufficient (pg.5 of the datasheet).

An arduino pin can source 40mA and I've found that a second pin directly bypassing the 4.7K pullup without the suggested transistor, will source enough current for at least 3 sensors (as many as I've tried so far) and I assume the technique could be extended to more pins. The strong pullup must be switched on within 10uSec after the Convert T command and kept on for the duration of the conversion. The 10uSec spec pretty much means you have to do this in the library.

I keep an abbreviated DS18B20 library around in which I assume the sensors on the bus are related, so it sets all of their resolutions at once and starts their conversions at once, and assumes that the bus is parasite-powered, which mine are, so it switches a specified pin as a strong pullup. I give up some flexibility that the full DSTemperature library would allow but it satisfies my temperature measuring requirements (so far) and simplifies my application code by black-boxing the above techniques.
> 3 votes

# Answer
Doing a search every time is quite inefficient. The search function is for if you don't know the device address - and it takes a while to do. In your case, presumably the addresses will never change. Find the addresses and hard-code them into your code. Or if that isn't practical, store them in EEPROM. And if even that isn't practical find the addresses once in setup.

---

Next, you need a delay while you take the temperature readings. Why not parallel those up? In a loop, tell all the devices to take a reading. Then wait one second. Then read them all (in another loop). That way the one-second delay is shared between all your sensors.

However from the page Gerben linked:

> And it is NOT possible to run DS1820 sensors on a simple pull-up resistor. During the "Conversion" phase, it needs more power. And there are Application Note discussing this in length.

That suggest that if you are using parasitic power, my suggestion won't work too well (having multiple devices taking readings would make it worse).

---

I found this code on my disk from a couple of years ago. There don't seem to be any delays between reading sensors. There is a delay at the end of the main loop, mainly to stop spamming the serial monitor.

Notice the comment:

> Call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus

See if that works for you.

```
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Streaming.h>

// Data wire is plugged into port 10 on the Arduino
const byte ONE_WIRE_BUS = 10;
const byte TEMPERATURE_PRECISION = 10;
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress myThermometer [10];
int deviceCount;

void setup(void)
{

  // start serial port
  Serial.begin (115200);
  Serial << "Dallas Temperature IC Control Library Demo" << endl;

  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial << "Locating devices..." << endl;
  deviceCount = sensors.getDeviceCount();

  Serial << "Found " << deviceCount << " devices." << endl;

  // report parasite power requirements
  Serial << "Parasite power is: " << (sensors.isParasitePowerMode() ? "ON" : "OFF") << endl;

  // method 1: by index

  for (int i = 0; i < deviceCount; i++)
  {
    if (sensors.getAddress(myThermometer [i], i))
    {
      Serial << "Device " << i << " Address: ";
      printAddress(myThermometer [i]);
      Serial << endl;
      sensors.setResolution(myThermometer [i], TEMPERATURE_PRECISION);
    }
    else
      Serial << "Unable to find address for Device " << i << endl;
  }  // end of for loop

}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

void loop(void)
{

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures();

  // now get all temperatures
  for (int i = 0; i < deviceCount; i++)
  {
    float tempC = sensors.getTempC(myThermometer [i]);
    if (tempC > -80)
    {
      Serial << "Device " << i << " Temperature: " << tempC << endl;
    }
    else
      Serial << "Unable to find temperature for Device " << i << endl;
  }  // end of for loop

  delay (1000);
}

```
> 2 votes

# Answer
In case the "Temperature Conversion Time (tCONV)" of each resolution is not fast enough (\[MAX\] 9-bit: 93.75ms; 10-bit: 187.5ms; 11-bit resolution: 375ms; 12-bit: 750ms), you can use more sensors.

For example, to get a half time (for 9-bit): 47ms:

* You can use two sensors at the same measurement point, (they can operate in parallel , as long as the software can operate with each one of them) when reading one, the software starts converting the other.

Each one has its normal conversion time, but when doing the readings in an interleaved way, a shorter reading time can be obtained.

For 8 sensors, a time below 11.75ms can be achieved (for 9-bit).
> 0 votes

---
Tags: programming, temperature-sensor
---


# Question
Title: Maduino (Arduino Zero) at91samd21g18 - Unable to connect to the serial port
I have been using this device very little but it was use to work, and it also gave me the same issue in the past, the somewhat I was able to upload again.

I tried to use the reset button, and short GRD with RST pins, but nothing helped. The device is recognised as **Arduino MRK1000** and connected. I also tried to specify **Arduino Zero (Native USB Port)**. *Under Tools \> Get Board* Info I get:

```
BN: Arduino MKR1000
VID 0x2341
PID: 0X804E
SN: 414C4E1[...]

```

**My issue:**
When I try to upload the sketch (even empty) it hangs forever, or some times it shows the same message shown when you unplug the device while uploading.

```
No device found on COM5
Failed uploading: uploading error: exit status 1

```

The serial monitor is unable to connect

```
Sketch uses 33108 bytes (12%) of program storage space. Maximum is
262144 bytes. Global variables use 3552 bytes (10%) of dynamic memory,
leaving 29216 bytes for local variables. Maximum is 32768 bytes.
No device found on COM5 Failed uploading: uploading error: exit status 1

```

**Attempted resolution actions:**
I tried to use the reset button, and short GRD with RST pins, but nothing helped. I tried multiple USB ports, different PC, different cable.

**For information about the device:**
https://github.com/Makerfabs/Maduino-Zero-4G-LTE https://wiki.makerfabs.com/Maduino\_Zero\_4G\_LTE.html

**Requests:**
If you could guide me, maybe I can try to "factory reset" the MCU, or maybe try to connect in a different way.
I read about the bootloaders but I don't know how they work and I don't want to try alone and make worse.
The manufacturer didn't reply to my messages,on GitHub I didn't receive any reply either, so this is one last attempt before I throw this into the bin.
If anyone can recommend al alternative board with GPS and LTE/4G connectivity would be a plus.

# Answer
As suggested by Juraj (thank you), **pushing the reset button twice** allowed me to upload an empty sketch and "revive" an otherwise unusable device.
> 0 votes

---
Tags: serial, arduino-zero
---


# Question
Title: USB Host Shield plus 2 identical joysticks
I'm trying to get two identical joystics (Saitek cyborg 3D) running with the USB-Host-Shield on a Mega 2560 and an USB-Hub.

I already get the event-messages of both of them:

```
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>

// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

#include "hidjoystickrptparser.h"

USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid1(&Usb);    // first Joystick
HIDUniversal Hid2(&Usb);    // second Joystick

JoystickEvents Joy1Events;
JoystickEvents Joy2Events;

JoystickReportParser Joy1(&Joy1Events);
JoystickReportParser Joy2(&Joy2Events);

void setup() {
        Serial.begin(115200);
#if !defined(__MIPSEL__)
        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
        Serial.println("Start");

        if (Usb.Init() == -1)
                Serial.println("OSC did not start.");

        delay(200);

        if (!Hid1.SetReportParser(0, &Joy1))
                ErrorMessage<uint8_t > (PSTR("SetReportParser1"), 1);
        if (!Hid2.SetReportParser(0, &Joy2))
                ErrorMessage<uint8_t > (PSTR("SetReportParser2"), 1);
}

void loop() {
        Usb.Task();
        Serial.print("\tX1: ");
        PrintHex<uint8_t > (JoystickEvents::mostRecentEvent.X, 0x80);
        Serial.print("\tY1: ");
        PrintHex<uint8_t > (JoystickEvents::mostRecentEvent.Y, 0x80);
        Serial.print("\tX2: ");
        PrintHex<uint8_t > (JoystickEvents::mostRecentEvent.Z1, 0x80);
        Serial.print("\tY2: ");
        PrintHex<uint8_t > (JoystickEvents::mostRecentEvent.Z2, 0x80);
        Serial.print("\tRz: ");
        PrintHex<uint8_t > (JoystickEvents::mostRecentEvent.Rz, 0x80);
        Serial.println("");

}

```

My question is: How can I distinguish the events from the different joysticks.

I'm trying to get some kind of port-information from the USB-Hub. Unfortunately something like

```
!hid->GetAddress()

```

within the JoystickReportParser doesn't do the job as it always returns 0.

Any ideas?

# Answer
Not quite the question that was asked but part of the problem.

This is a simple introduction to pointers.

```
int variable = 42;                              // Create a variable
int* pointer = &variable;                       // Create a pointer to the variable (by getting its address)
*pointer = 99;                                  // Set the address to a new value
printf ("variable has the value %d", variable); // Print 99.

```

`&x` get the address of `x`

`*y` `dereferences` the pointer y, which means it 'turns it back to a variable' (this is simplistic view which isn't really true, but will do for now). So you could, if you wanted (which you wouldn't) do this `*&z` which would be the same as doing `z`.

Basically think of `&` and `*` as a pair of complimentary operators like - and + or * and /. (They aren't operators, but to start with it might help).

The next problem is when you do this

```
SomeFunction(&variable);

```

All function parameters in C/C++ are passed by value by default. This means the function gets a copy of them not the actual value. So if you had:

```
void FunctionOne (int val)
{
    val = 99;
}
int val = 4;
FunctionOne(val);
printf("val = %d", val);   // You will see 4 printed.

```

If you pass by reference then you will see 99 printed, to pass by reference you can do it one of two ways.

```
void FunctionTwo (int& valByRef);
void FunctionThree (int* valPointer);

```

`FunctionTwo` only works with C++ (It will work with an Arduino).

`FunctionThree` might cause a segmentation error if NULL is passed in and the function writes to it.

If it helps in my opinion pointers was one of the hardest concepts to grasp in classic C/C++ so don't worry if you don't understand it just have a play with it and see what you can do.

**Calling Methods**

* `object.method()` \- Call the function method on the instance called object which is of type `X`.
* `object->method()` \- Call the function method on the instance called object which is a **pointer** of type `X`.
* `object::method()` \- call the function method which is a static member of class object (static means it doesn't change any data within an instance of a class)
* \*object-\>method() - Avoid this like the plague. It either means `*(object->method())` or `(*object)->method()` to know you would need to look at the type of object and the return type of the function. Its easier just to bracket it to remove ambiguity.

As for `*object.&method()` I've never come across that one, but that doesn't mean it doesn't exist. :)
> 1 votes

# Answer
this could be a possible answer, in Arduino Code, the USB Host Shield 2.0 library is necessary:

```
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>

// Logitech Attack 3 HID report
struct GamePadEventData {
    uint8_t X, Y, Z1, Z2, Rz;
} __attribute__((packed));

class JoystickEvents {
    public: virtual void OnGamePadChanged(const GamePadEventData *evt, int joystick);
};

class JoystickReportParser : public HIDReportParser {
    JoystickEvents *joyEvents;
    uint8_t joyId;
    uint8_t oldPad[sizeof(GamePadEventData)];
    public: JoystickReportParser(JoystickEvents *evt, uint8_t id) : joyEvents(evt), joyId(id) {}
    virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
    if (!is_rpt_id && len == sizeof(GamePadEventData)) {
        // Checking if there are changes in report since the method was last called
        bool match = (sizeof(oldPad) == len) && (memcmp(oldPad, buf, len) == 0);
        if (!match && joyEvents) {
            joyEvents->OnGamePadChanged((const GamePadEventData*)buf, joyId);
            memcpy(oldPad, buf, len);
        }
    }
}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt, int joystick) {
    Serial.print("Joystick ");
    Serial.print(joystick);
    Serial.print(": X: "); PrintHex<uint16_t>(evt->X, 0x80);
    Serial.print(" Y: "); PrintHex<uint16_t>(evt->Y, 0x80);
    Serial.print(" Z1: "); PrintHex<uint8_t>(evt->Z1, 0x80);
    Serial.print(" Z2: "); PrintHex<uint8_t>(evt->Z2, 0x80);
    Serial.print(" Rz: "); PrintHex<uint8_t>(evt->Rz, 0x80);
    Serial.println();
}

USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid1(&Usb); // first Joystick
HIDUniversal Hid2(&Usb); // second Joystick

JoystickEvents JoyEvents;
JoystickReportParser Joy1(&JoyEvents, 1);
JoystickReportParser Joy2(&JoyEvents, 2);

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

    Serial.println("Start");

    if (Usb.Init() == -1) {
        Serial.println("OSC did not start.");
    }

    delay(200);

    if (!Hid1.SetReportParser(0, &Joy1) || !Hid2.SetReportParser(1, &Joy2)) {
        ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1);
    }

}

void loop() {
    Usb.Task();
}

```
> 0 votes

---
Tags: usb, joystick
---


# Question
Title: manage some output based on some parameter and rtc
i'm trying to create a program that given a configuration (i've used multiple struct nested) i need in loop() to check for each output if they need to be on or off and set the output accordingly

let me explain the configuration (i'm not sure that this is the best way to make and store this config, suggestions are appreciated)

```
struct Period
{
    String name;
    String type;
    String value;
};

struct State
{
    String name;
    Period periods[2];
};

struct Output
{
    String name;
    int pin;
    int forcePin;
    State states[2];
};

Output outputs[4];

```

now i populate the first object (this is something that need to be editable by the user and i was thinking to store it in the EEPROM, for now in the setup() i do this

```
    outputs[0].name = "OUTPUT 1";
    outputs[0].pin = 27;
    outputs[0].forcePin = 25;
    outputs[0].states[1].name = "STATE 1";
    outputs[0].states[1].periods[0].name = "day";
    outputs[0].states[1].periods[0].type = "BOOL";
    outputs[0].states[1].periods[0].value = "ON";
    outputs[0].states[1].periods[1].name = "night";
    outputs[0].states[1].periods[1].type = "BOOL";
    outputs[0].states[1].periods[1].value = "OFF";
    outputs[0].states[0].name = "STATE 2";
    outputs[0].states[0].periods[0].name = "day";
    outputs[0].states[0].periods[0].type = "BOOL";
    outputs[0].states[0].periods[0].value = "ON";
    outputs[0].states[0].periods[1].name = "night";
    outputs[0].states[0].periods[1].type = "BOOL";
    outputs[0].states[0].periods[1].value = "OFF";

```

then in the loop i have few function that determinate the state and period and i call this function that should manage all the outputs globalState in loop read from an input and set the variable globalPeriod check the time and set if night or day

```
void manageOutputs()
{
    for (Output out : outputs)
    {
        Serial.println(out.name);
        Serial.println(out.pin);
        Serial.println(out.forcePin);
        if (digitalRead(out.forcePin) == LOW)
        {
            Serial.println("forced on set output");
            digitalWrite(out.pin, HIGH)
            continue;
        }

        Serial.println(out.states[globalState].name);
        Serial.println(out.states[globalState].periods[globalPeriod].name);
        Serial.println(out.states[globalState].periods[globalPeriod].type);
        Serial.println(out.states[globalState].periods[globalPeriod].value);
        if (out.states[globalState].periods[globalPeriod].type.equals("BOOL")) {
            if (out.states[globalState].periods[globalPeriod].value.equals("ON")) {
                digitalWrite(out.pin,HIGH);
            } else {
                digitalWrite(out.pin,LOW);
            }
        }
    }
}

```

i have multiple type of output in mind for example TIMER (so in the value field i would have some parameter to call another function that will alternate the output on and off for the time given) will have something like "15:10" so it will stay 15 minutes on and 10 minutes off, or a condition (for example if VAR1 \> 50) so the field value would have "VAR1:\>:50" so it will turn on only if the condition is met. So i will have a switch case where now i check if BOOL.

now that i hope that i have explained the situation, i would like to know if it's a good way to have 3 nested struct or if there is a better solution considering the necessity to have it stored in EEPROM, and if this is a good way to have this kind of condition like this or if there is a better way. Considering also that in the future i would like to make a webpage or an api to update this kind of configuration from a pc (maybe using a esp-8266 for that, that is also connected to the arduino, or do everything with an esp32, but i would like first to have the basic loop working and then i will make the "UI")

thanks a lot

# Answer
There are many uses of the `String` class in these code snippets. Using strings is quite natural in some higher-level languages. On an Arduino, however, I would strongly advise you against this for two reasons:

1. String objects use dynamic memory, which is not friendly to the small amount of RAM available on a typical Arduino.
2. Saving a String to EEPROM is not trivial: you do not want to save the String object (it contains a pointer that would not make sense in EEPROM context), and you instead have to save the character array it refers to. This could involve handling complex memory allocation withing the EEPROM.

Instead of a string meant to handle one of a predefined set of values (`"BOOL"`, `"TIMER"`, ...), use an `enum`. This is similar to an `int`, where each possible value has been given a name (`TYPE_BOOL` is 0, `TYPE_TIMER` is 1, ...). Instead of a string holding numbers, store the numbers themselves. In essence, you want to create a data storage format that is friendly to the binary nature of the CPU. If you really have to store strings, e.g. for names (are those `name` fields really useful? they do not look so in the provided example), limit their length and store them as fixed-size character arrays.

The `period::value` field is interesting in that it can store different kinds of information depending on the `type` field. For such a situation the appropriate data structure is a discriminated union. A `union` is like a `struct` except that all fields share the same memory space and only one can be valid at a time. In a discriminated union, the `union` is accompanied by a `ytpe` field that tells us which is the valid field.

Applying those principles to your problem could give this kind of data structure:

```
// All the possible Period types.
enum Type {
    TYPE_BOOL,
    TYPE_TIMER,
    // etc.
};

// This is a discriminated union.
struct Period
{
    Type type;
    union {  // one union member per possible type.
        bool bool_value;  // valid when type == TYPE_BOOL
        struct {
            int on_time;
            int off_time;
        } timer_value;  // valid when type == TYPE_TIMER
        // etc.
    };
};

struct State
{
    Period periods[2];
};

struct Output
{
    int pin;
    int forcePin;
    State states[2];
};

```

These data structures can be trivially saved in EEPROM, as they are self-contained: they hold no pointers to data stored in dynamic memory.

Then, in `manageOutputs()`, you will read a period's `bool_value` only when `type` is `TYPE_BOOL`, it's `timer_value` only when `type` is `TYPE_TIMER`, etc:

```
void manageOutputs()
{
    for (Output out : outputs)
    {
        if (digitalRead(out.forcePin) == LOW) {
            digitalWrite(out.pin, HIGH);
            continue;
        }
        Period &period = out.states[globalState].periods[globalPeriod];
        switch (period.type) {
            case TYPE_BOOL:
                if (period.bool_value) {
                    digitalWrite(out.pin, HIGH);
                } else {
                    digitalWrite(out.pin, LOW);
                }
                break;
            case TYPE_TIMER:
                digitalWrite(out.pin, HIGH);
                delay(period.timer_value.on_time);
                digitalWrite(out.pin, LOW);
                delay(period.timer_value.off_time);
        }
    }
}

```
> 0 votes

---
Tags: eeprom, loop, struct
---


# Question
Title: attachInterrupt has no effect on Industruino SAMD21
I'm using Industruino D21G (SAMD21G version) with Visual Studio Code extension for Arduino. `attachInterrupt` seems to have no effect. I tried Industruino CH1, CH6 and CH7 with the same result. When I poll these channels in a loop, I detect signal level change as expected. Here is the code:

```
#include <Arduino.h>
#include <Indio.h>

constexpr int PROXIMITY_SENSOR_NC = 6;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Indio.digitalMode(PROXIMITY_SENSOR_NC, INPUT);
  attachInterrupt(digitalPinToInterrupt(PROXIMITY_SENSOR_NC), blink, FALLING);
  digitalWrite(LED_BUILTIN, HIGH);
}

void blink() {
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

void loop() {
}

```

Any ideas what could be wrong?

# Answer
Industrial level I/O on Industruino, which includes CH1, CH6 and CH7 I tried, is not connected directly to the microcontroller. It uses a buffer and communicates through I2C in pull mode. That's why interrupt on I/O change has no effect.
> 1 votes

---
Tags: interrupt, samd21g
---


title: Help to set vertical dcroll on SSD1306

text:
# Question
Title: Help to set vertical dcroll on SSD1306
I am trying to set the text to scroll vertically. I have a big chunk of text (example in the code below) to be set to scroll vertically. What I want is to display the complete text on the screen. Presently it scrolls the complete chunk of text. Any help or guidance is heartily welcome.

```
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Sometimes we dont want to scroll entire display. ");
  display.startscrollright(0x00, 0x0F);

  display.display();

  delay(1000);
}
void loop(){

}

```

The link to the project is here: https://wokwi.com/arduino/projects/302023407584674313

**3rd edit**

My question:

My goal is to display the text in the window. The text should not go out of the window. If the text is too long, it should scroll vertically.

Thanks again, everyone.

# Answer
> 1 votes
This line achieved it for me. I stole it from here: Adafruit Forum

```
display.startscrolldiagright(0x0F, 0x0F);

```

It sets diagonal scroll, but start and stop positions are multiples of the display width so that in total, it scrolls vertically up.

Alternatively, you edit the display buffer; by removing your content from the current position, deleting the first line of pixels, adding a new last line of pixels, writing it all back to the display buffer and then call `display.display()`.

This is not exactly saving your microcontroller time but it works, too. I asked ChatGpt to do the coding for the second solution, it delivered. I won't post the code here though, as it is against the rules.

---
Tags: ssd1306
---


title: Mobile hotspot with wemos d1 mini

text:
# Question
Title: Mobile hotspot with wemos d1 mini
I recently got a wemos d1 mini and now am trying to connect it to my IPhone 13's hotspot, however it doesn't connect, I tried to run the wifiscan example - and it doesn't even detect it there.

I tried connecting it to my home router - and this worked hence I have no ideas on fixing it, so any help would be appreciated!

# Answer
By default the iPhone hotspot is 5GHz only, which is why your ESP8266 can't see it. The ESP8266's WiFi radio is 2.4GHz only.

To enable 2.4GHz on the iPhone hotspot, turn on the "Maximize Compatibility" button under "Settings | Personal Hotspot". Then 2.4GHz devices should be able to connect to the phone.
> 4 votes

---
Tags: esp8266, wifi, networking
---


# Question
Title: Having issues understanding what "#define GET_STATUS" does
I am trying to use a Waveshare 4.2inch e-paper display with an Adafruit Feather Adalogger M0, but am having issues with two separate instances of `#define GET_STATUS` being defined differently in different locations. More specifically, in the Demo Library (download) for the Waveshare display, one of the files (epd4in2.h) defines GET\_STATUS as 0x71. However, in a file (USBCore.h) I downloaded from the board manager in the ArduinoIDE to be able to support the Feather Adalogger, GET\_STATUS is defined as 0.

I've tried messing with the values to see if making them match (both as 0x71 and both as 0) would solve the issue, but it didn't change anything. I can't find any information about what GET\_STATUS in general, so I'm unsure what I can even try to fix this issue. Furthermore, I can't find any instances of GET\_STATUS being used, so I'm unsure what its significance even is. So, basically, my questions are: 1) what is the significance of GET\_STATUS, and 2) how can I reconcile it being used differently in two different places?

Below is the code I'm trying to run (it's the demo code from Waveshare), and the libraries other than "\<SPI.h\>" are in the demo library download from Waveshare.

```
#include <SPI.h>
#include "epd4in2.h"
#include "imagedata.h"
#include "epdpaint.h"

#define COLORED     0
#define UNCOLORED   1

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

  if (epd.Init() != 0) {
    Serial.print("e-Paper init failed");
    return;
  }

  /* This clears the SRAM of the e-paper display */
  epd.ClearFrame();

  /**
    * Due to RAM not enough in Arduino UNO, a frame buffer is not allowed.
    * In this case, a smaller image buffer is allocated and you have to
    * update a partial display several times.
    * 1 byte = 8 pixels, therefore you have to set 8*N pixels at a time.
    */
  unsigned char image[1500];
  Paint paint(image, 400, 28);    //width should be the multiple of 8

  paint.Clear(UNCOLORED);
  paint.DrawStringAt(0, 0, "e-Paper Demo", &Font24, COLORED);
  epd.SetPartialWindow(paint.GetImage(), 100, 40, paint.GetWidth(), paint.GetHeight());

  paint.Clear(COLORED);
  paint.DrawStringAt(100, 2, "Hello world", &Font24, UNCOLORED);
  epd.SetPartialWindow(paint.GetImage(), 0, 64, paint.GetWidth(), paint.GetHeight());

  paint.SetWidth(64);
  paint.SetHeight(64);

  paint.Clear(UNCOLORED);
  paint.DrawRectangle(0, 0, 40, 50, COLORED);
  paint.DrawLine(0, 0, 40, 50, COLORED);
  paint.DrawLine(40, 0, 0, 50, COLORED);
  epd.SetPartialWindow(paint.GetImage(), 72, 120, paint.GetWidth(), paint.GetHeight());

  paint.Clear(UNCOLORED);
  paint.DrawCircle(32, 32, 30, COLORED);
  epd.SetPartialWindow(paint.GetImage(), 200, 120, paint.GetWidth(), paint.GetHeight());

  paint.Clear(UNCOLORED);
  paint.DrawFilledRectangle(0, 0, 40, 50, COLORED);
  epd.SetPartialWindow(paint.GetImage(), 72, 200, paint.GetWidth(), paint.GetHeight());

  paint.Clear(UNCOLORED);
  paint.DrawFilledCircle(32, 32, 30, COLORED);
  epd.SetPartialWindow(paint.GetImage(), 200, 200, paint.GetWidth(), paint.GetHeight());

  /* This displays the data from the SRAM in e-Paper module */
  epd.DisplayFrame();

  /* This displays an image */
  epd.DisplayFrame(IMAGE_BUTTERFLY);

  /* Deep sleep */
  epd.Sleep();
}

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

}

```

When I run the code, I get the following messages

```
In file included from /home/beingpool/Arduino/epd4in2-demo/epd4in2-demo.ino:28:
/home/<user>/Arduino/libraries/epd4in2/epd4in2.h:64: warning: "GET_STATUS" redefined
   64 | #define GET_STATUS                                  0x71
      |
In file included from /home/beingpool/.arduino15/packages/adafruit/hardware/samd/1.7.11/cores/arduino/Arduino.h:157,
                 from /home/beingpool/.var/app/cc.arduino.IDE2/cache/arduino/sketches/96EFEDEA56FF573B678089A960FFC685/sketch/epd4in2-demo.ino.cpp:1:
/home/beingpool/.arduino15/packages/adafruit/hardware/samd/1.7.11/cores/arduino/USB/USBCore.h:23: note: this is the location of the previous definition
   23 | #define GET_STATUS     0
      |

```

# Answer
> 0 votes
There is no generic meaning in `GET_STATUS`. Apparently both libraries use the very same identifier for their own different purpose.

If you do not use `GET_STATUS` in your sketch, you can remove the definition before the inclusion of "epd4in2.h", like this:

```
#include <SPI.h>
#undef GET_STATUS
#include "epd4in2.h"

// ...

```

---
Tags: library, adafruit, display, feather
---


# Question
Title: Arduino-project with color sensor and rgb-led
I want to use a color sensor for my Arduino project with Arduino Uno to detect the colors red, green, blue, orange, yellow purple of leaves of paper and then light my RGB led in those colors. I have no errors in my code, but it fails for some reason :( Can someone help me?

here is the code:

```
#define s0 8
#define s1 9
#define s2 10
#define s3 11
#define sensorOut 12

#define LED_RED 3
#define LED_GREEN 5
#define LED_BLUE 6

// Variabelen voor de kleurwaarden
int red;
int green;
int blue;

const int RED_COLOR = (255, 0, 0);
const int GREEN_COLOR = (0, 255, 0);
const int BLUE_COLOR = (0, 0, 255);
const int ORANGE_COLOR = (255, 165, 0);
const int PINK_COLOR = (255, 105, 180);
const int PURPLE_COLOR = (128, 0, 128);
const int YELLOW_COLOR = (255, 255, 0);

int color = 0;

void setup() {
  // Zet de seriële communicatie op
  Serial.begin(9600);

  // Initialiseer de pinmodi
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pinMode(sensorOut, INPUT);

  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);

  // Zet de frequentie van de kleurensensor op 20% (rode filter)
  digitalWrite(s0, HIGH);
  digitalWrite(s1, LOW);
}

void loop() {
  // Lees de kleurwaarden
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  red = pulseIn(sensorOut, digitalRead(sensorOut) == HIGH ? LOW : HIGH);
  delay(20);
  digitalWrite(s3, HIGH);
  blue = pulseIn(sensorOut, digitalRead(sensorOut) == HIGH ? LOW : HIGH);
  delay(20);
  digitalWrite(s2, HIGH);
  green = pulseIn(sensorOut, digitalRead(sensorOut) == HIGH ? LOW : HIGH);
  delay(20);

// Controleer op verschillende kleuren
if (red > green && red > blue) {
  color = RED_COLOR; // Rood
} else if (green > red && green > blue) {
  color = GREEN_COLOR; // Groen
} else if (blue > red && blue > green) {
  color = BLUE_COLOR; // Blauw
} else if (red > green && red > blue && green > blue) {
  color = YELLOW_COLOR; // Geel
} else if (red > green && red > blue && blue > green) {
  color = ORANGE_COLOR; // Oranje
} else {
  color = 0; // Geen herkende kleur
}

  // Controleer op verschillende kleuren
  if (color == RED_COLOR) {
    setColor(255, 0, 0); // Rood
  } else if (color == GREEN_COLOR) {
    setColor(0, 255, 0); // Groen
  } else if (color == BLUE_COLOR) {
    setColor(0, 0, 255); // Blauw
  } else if (color == ORANGE_COLOR) {
    setColor(255, 165, 0); // Oranje
  } else if (color == PINK_COLOR) {
    setColor(255, 105, 180); // Roze
  } else if (color == PURPLE_COLOR) {
    setColor(128, 0, 128); // Paars
  } else if (color == YELLOW_COLOR) {
    setColor(255, 255, 0); // Geel
  } else {
    // Geen herkende kleur, zet de led uit
    setColor(0, 0, 0);
  }

  delay(500); // Wacht 500 milliseconden voordat je de volgende kleur controleert
}

// Hulpmethode om de RGB-waarden in te stellen
void setColor(int red, int green, int blue) {
  analogWrite(LED_RED, red);
  analogWrite(LED_GREEN, green);
  analogWrite(LED_BLUE, blue);
}

```

# Answer
> 1 votes
Reading your code, I see three points:

1. Your constants are not assigned the values that you think. `const int RED_COLOR = (255,0,0);` sets the integer constant to the value `0`, i.e. the last value of a comma-separated sequence, see here. Instead, enumerate your color constants, i.e. set red=1, blue=2, etc. Or define a struct with three integer components.
2. The variable `color` will never be assigned the values `ORANGE_COLOR`, `PURPLE_COLOR` nor `YELLOW_COLOR`, because of the way you structured the expressions in the if-then-else block. If `red > green && red > blue`, the program will never even check whether `red > green && red > blue && blue > green`, because it already entered the first block. And `PURPLE_COLOR` is not listed in the upper if-else-block at all. Also, I would expect some `CYAN_COLOR` somewhere in there to cover the shades between green and blue.
3. What is the exact type of the color sensor? It seems strange to me that it transmits its data via the length of a pulse. If it doesn't, `pulseIn()` is the wrong method to use. If it really does, you may have a race condition here: I guess that writing to the pins `s2`/`s3` triggers the sensor to start the "data pulse", in which case `digitalRead(sensorOut)` may already return the "pulse state" instead of the "pre-pulse state" and therefore waits for a different pulse than it should. You'd need to first read `sensorOut` into a variable, then set `s2`/`s3`, then read your data via `pulseIn` using the variable you set before.

But without having the datasheet of the sensor/knowing the protocol of the sensor, this is all very volatile guesswork. Please improve your question by adding the sensor type (and maybe a wiring diagram) alongside an explanation of what you mean by "it fails". How exactly does it fail? Which part works and which doesn't?

You can also glean more insight into the state of your sketch by writing measured values to the serial monitor using `Serial.println`.

---
Tags: arduino-uno, programming, sensors, rgb-led, project
---


# Question
Title: what is 400 bad request and how to solve this
```
AT+CIPSEND=65
link is not valid

ERROR

OK

OK

OK

OK
STATUS:2

OK
\x0BQ\xADUART_DEF=115200,8,1,0,0ATE0
AT+CWMODE=3
AT+CIPMUX=0
AT+CIPMODE=0
AT+CIPSTATUS
AT+CIPSTART="TCP","api.thingspeak.com",80
AT+CIPSTATUS
CONNECT

OK
STATUS:3
+CIPSTATUS:0,"TCP","52.0.107.28",80,38071,0

OK

OK
> AT+CIPSEND=65
GET api.thingspeak.com/update?api_key=M
Recv 65 bytes
E5K4JWXT2ZBSBZ8&field1=0

SEND OK

+IPD,272:HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Tue, 23 May 2023 05:45:13 GMT
Content-Type: text/html
Content-Length: 122
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
</body>
</html>
CLOSED

```

# Answer
> 1 votes
The server name does not belong to the `GET` request line: it has to be provided in the `Host` request header.

Try something this:

```
server.println("GET /update?api_key=ME5K4JWXT2ZBSBZ8&field1=0 HTTP/1.0");
server.println("Host: api.thingspeak.com");
server.println();  // empty line means "end of request headers"

```

---
Tags: esp8266, iot
---


# Question
Title: Same Bin file to similar ESP32 boards yields different results
Sorry for the confusing title. It is a bit hard to explain.

We have a remote developer who compiles his code into a bin file and sends it to all of us. He loads it onto his ESP32 boards and they work just fine. However, when we load the bin file onto our ESP32 boards, they do not work. We are all using the same configuration ESP32 boards. We are all using Expressif Flash Download tool to load the bin file.

Where would y'all recommend I start my investigation? What additional info do you need from me to help figure this out? I have confirmed that we are all using the same ESP32 boards as well as the same flash tool. Ideas?

By the way, I am not the programmer, I do not have access to the source code. I only have the bin file.

Thank you

# Answer
My fault. I hadn't wired the final product exactly as the designer had. Once the wiring was correct the issue was resolved. Just needed a physical troubleshooting as the software troubleshooting wasn't the issue.

Funny thing is, there are only two wires on the entire project and I had gotten them wrong.

So I think the lesson here is, check your physical configuration as well as the software/firmware.

Thank you all for your help.
> 0 votes

---
Tags: esp32, firmware
---


# Question
Title: How do I control the buttons on an Arduino LCD keypad shield?
I have just bought a 16x2 LCD display with buttons. I can get the display to work and do various basic sketches included in the Arduino IDE. However, I cannot figure out how to control the buttons.

The buttons work using analog pin 0 and from what I was able to understand from what I have read online, it is something to do with the values you receive when the buttons are pressed. I can't seem to find out what values mine gives, I have found a sketch that is supposed to map the buttons, but I cannot get it to work, as I don't really understand what it is doing, I am very new to this.

The code I am using is as follows:

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int lcd_key     = 0;
int adc_key_in  = 0;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

int read_LCD_buttons() {
  adc_key_in = analogRead(0);
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 600)  return btnLEFT;
  if (adc_key_in < 920)  return btnSELECT;
  return btnNONE;
}

void setup() {
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("Push the buttons");
}

void loop() {
  lcd.setCursor(9, 1);
  lcd.print(millis()/1000);
  lcd.setCursor(0, 1);
  lcd_key = read_LCD_buttons();
  switch (lcd_key) {
    case btnRIGHT: {
      lcd.print("RIGHT ");
      break;
    }
    case btnLEFT: {
      lcd.print("LEFT   ");
      break;
    }
    case btnUP: {
      lcd.print("UP    ");
      break;
    }
    case btnDOWN: {
      lcd.print("DOWN  ");
      break;
    }
    case btnSELECT: {
      lcd.print("SELECT");
      break;
    }
    case btnNONE: {
      lcd.print("NONE  ");
      break;
    }
  }
}

```

If anyone can give me any pointers it would be greatly appreciated.

Liam

# Answer
I have found an easy way to do this, i found a tutorial on instructables that has explained in detail what to do, i then applied this to my LCD keypad shield rather than external buttons on a breadboard.

All you have to do to see what the results are for your particular buttons is to load the sketch below onto your board then open the serial mapper on the arduino ide, simply press the buttons and you should see the results.

```
 /*
  Debounce

  Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
  press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
  a minimum delay between toggles to debounce the circuit (i.e. to ignore
  noise).

  created 28 October 2009
  by Riaan Cornelius

  */

 // constants won't change. They're used here to
 // set pin numbers:
 const int buttonPin = 0;     // the number of the pushbutton pin
 const int ledPin =  53;      // the number of the LED pin for testing

 const int BUTTON1 = 1;
 const int BUTTON2 = 2;
 const int BUTTON3 = 3;
 const int BUTTON4 = 4;
 const int BUTTON5 = 5;

 const int BUTTON1LOW = 970;
 const int BUTTON1HIGH = 1024;
 const int BUTTON2LOW = 850;
 const int BUTTON2HIGH = 950;
 const int BUTTON3LOW = 700;
 const int BUTTON3HIGH = 800;
 const int BUTTON4LOW = 400;
 const int BUTTON4HIGH = 650;
 const int BUTTON5LOW = 250;
 const int BUTTON5HIGH = 350;

 // Variables will change:
 int ledState = HIGH;         // the current state of the output pin
 int buttonState;             // the current reading from the input pin
 int lastButtonState = LOW;   // the previous reading from the input pin

 // the following variables are long's because the time, measured in miliseconds,
 // will quickly become a bigger number than can be stored in an int.
 long lastDebounceTime = 0;  // the last time the output pin was toggled
 long debounceDelay = 50;    // the debounce time; increase if the output flickers

 void setup() {
   pinMode(buttonPin, INPUT);
   pinMode(ledPin, OUTPUT);
   Serial.begin(9600);
 }

 void loop() {
   // read the state of the switch into a local variable:
   int reading = analogRead(buttonPin);
   Serial.println(reading);

   /*
   Not needed while getting the values.

   int tmpButtonState = LOW;             // the current reading from the input pin

   if(reading>BUTTON5LOW && reading<BUTTON5HIGH){
     //Read switch 5
     tmpButtonState = BUTTON5;
   }else if(reading>BUTTON4LOW && reading<BUTTON4HIGH){
     //Read switch 4
     tmpButtonState = BUTTON4;
   }else if(reading>BUTTON3LOW && reading<BUTTON3HIGH){
     //Read switch 3
     tmpButtonState = BUTTON3;
   }else if(reading>BUTTON2LOW && reading<BUTTON2HIGH){
     //Read switch 2
     tmpButtonState = BUTTON2;
   }else if(reading>BUTTON1LOW && reading<BUTTON1HIGH){
     //Read switch 1
     tmpButtonState = BUTTON1;
   }else{
     //No button is pressed;
     tmpButtonState = LOW;
   }

   // check to see if you just pressed the button
   // (i.e. the input went from LOW to a buttonState),  and you've waited
   // long enough since the last press to ignore any noise:

   // If the switch changed, due to noise or pressing:
   if (tmpButtonState != lastButtonState) {
     // reset the debouncing timer
     lastDebounceTime = millis();
   }

   if ((millis() - lastDebounceTime) > debounceDelay) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     buttonState = tmpButtonState;
     Serial.println(buttonState);
   }

   // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastButtonState = tmpButtonState;

   // set the LED using the state of the button for testing:
   switch(buttonState){
     case BUTTON1:
     digitalWrite(ledPin, buttonState>0);
     break;
     case BUTTON2:
     digitalWrite(ledPin, buttonState>0);
     break;
     case BUTTON3:
     digitalWrite(ledPin, buttonState>0);
     break;
     case BUTTON4:
     digitalWrite(ledPin, buttonState>0);
     break;
     case BUTTON5:
     digitalWrite(ledPin, buttonState>0);
     break;
   }
   */
 }

```

Liam
> 2 votes

# Answer
Upload this and it will read the resistance of your buttons on the lcd screen

```
/*  /*
Arduino 2x16 LCD Detect Buttons
resistance
*/

#include <LiquidCrystal.h>

//LCD pin to Arduino
const int pin_RS = 8;
const int pin_EN = 9;
const int pin_d4 = 4;
const int pin_d5 = 5;
const int pin_d6 = 6;
const int pin_d7 = 7;

const int pin_BL = 10;

LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);

void setup() {

  lcd.begin(16, 2);

  lcd.setCursor(0,0);

  lcd.print("  Press Any Key ");
  lcd.setCursor(0,1);
  lcd.print("Resistance:");
}

void loop() {
  int x;
  x = analogRead (0);
  lcd.setCursor(12,1);
  lcd.print (analogRead (0));
  lcd.print("                ");
  delay (500);
  }

```
> 0 votes

---
Tags: lcd
---


# Question
Title: Arduino UNO stuck at 'uploading' with base sketch, nothing wired
This question has been asked before and I have carefully read the other questions, but the solutions have not worked in my case, and the details are not the same as mine.

**Description**

The Arduino Uno is stuck at uploading with the error `avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00`, with the base sketch.

**Details**

* I am trying with the base empty sketch.
* Nothing is wired, nothing connected

**Important Remarks**

* A second Arduino UNO works perfectly fine with the same setup
* Loopback test worked - Loopback test instructions
* Cable and drivers work fine
* Correct port is selected
* Rebooting, resetting, upgrading the Arduino IDE have not solved the problem

**Important details**

* The TX LED is slightly but constantly on, and measuring the value of the TX Pin (Digital 1) outputs a value of 2.0 V. This also happens when feeding the Arduino with a 12 V supply, without USB. **EDIT** Got rid of this part by burning the bootloader via ISP with another Arduino - Bootloader burn instructions
* Checking the COM devices via powershell `mode` outputs something different between the two Arduinos: a locked value of `Baud: 115200` for the one not working, while for the one that works it displays `Baud: None`.

# Answer
> 0 votes
> A second Arduino UNO works perfectly fine with the same setup

Sounds like your Uno is faulty. You could read my post here:

Have I bricked my Arduino Uno? Problems with uploading to board

Also What happens when code is uploaded using the bootloader?

The Unos should be simply replaceable. That is, if your setup works on one, then unless you have done something weird to the other one (such as changing the fuses) then that should work too.

Is it a genuine one? Or a cheap knock-off? If it's cheap, well you got what you paid for. Get another.

I have a post on my forum which lets you detect chip signatures and fuses (use your working Uno to run that). It may shed some light on what is happening.

---
Tags: arduino-uno, uploading, avrdude
---