message:
Stuck making multi, many button, joysticks

I'm stuck, I figured I'd ask here for some help... Note I'm a newb and this is essentially my first Arduino project beyond blink...

I'm creating Virtual cockpit panels for DCS World, using an Arduino Leonardo as an HID device. I'm using three SN74HC165 Shift-In registers for multi-buttons (24) - as it seemed the easiest - and all in all it does work...

So I figured that I'm using only 4 pins on the Leonardo, so why not try to setup 3 of these "shift-in clusters" (12 pins) to appear as 3 separate joysticks?

I got the one working and I got 2 more joysticks showing up in Windows10... now my problem is: how would I setup 2 more "shiftIn Clusters", I've tried many things but I must defer to outside help (cause I really don't know what I'm doing)

Edit to clarify: So each joystick need 3 or 4 shift registers making 24-32 buttons on each joystick

Shift In Lib: https://github.com/…/Ardu…/blob/master/ShiftIn/src/ShiftIn.h

Joy2 Lib: https://github.com/MHeironimus/ArduinoJoystickLibrary

Here's an image of the Layout I want: https://i.stack.imgur.com/sEtRp.png

... any help would relieve a great headache, Thank for your time

    #include <ShiftIn.h>
    #include <Joystick.h>

    // use <n> shift registers
    ShiftIn<3> shift;             // use three shift register

    // Create joystick
    // TESTING MULTI JOYSTICKS
    // 1/3 Works!!!
    // 3/3 Appear in Windows
    // ????? must add shiftIn sections for 2nd and 3rd joysticks????
    // (add pin usage + modify line 77-79 stuff)

    #define JOYSTICK_COUNT 3
    Joystick_ Joystick[JOYSTICK_COUNT] = {
      Joystick_(0x03, JOYSTICK_TYPE_GAMEPAD, 32, 0, false, false, false, false, false, false, false, false, false, false, false),
      Joystick_(0x04, JOYSTICK_TYPE_GAMEPAD, 32, 0, false, false, false, false, false, false, false, false, false, false, false),
      Joystick_(0x05, JOYSTICK_TYPE_GAMEPAD, 32, 0, false, false, false, false, false, false, false, false, false, false, false),
    };

    // Set to true to test "Auto Send" mode or false to test "Manual Send" mode.
    //const bool testAutoSendMode = true;
    const bool testAutoSendMode = false;

    const unsigned long gcCycleDelta = 1000;
    const unsigned long gcAnalogDelta = 25;
    const unsigned long gcButtonDelta = 500;
    unsigned long gNextTime = 0;
    unsigned int gCurrentStep = 0;
    int gJoystickId = 0;

    /*
    // WORKING SECTION Single Joystick with Shift Reg
    Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD,
      32, 0,                        // Button Count, Hat Switch Count
      false, false, false,          // X and Y, but no Z Axis
      false, false, false,          // No Rx, Ry, or Rz
      false, false,                 // No rudder or throttle
      false, false, false);         // No accelerator, brake, or steering
    */

    void setup() {

      shift.begin(8, 9, 11, 12);  // set pins of the shift register
    //  shift[1].begin(7, 6, 5, 4);  // set pins of the shift register
    //  shift[2].begin(3, 2, 1, 0);  // set pins of the shift register

     Joystick[0].begin();
     Joystick[1].begin();
     Joystick[2].begin();
    }

    void loop() {

      if (shift.update()) {
        for (int i = 0; i < shift.getDataWidth(); i++)
        Joystick[0].setButton(i, shift.state(i));            // just press or release the button
      }
    /*if (shift[1].update()) {
        for (int i = 0; i < shift[1].getDataWidth(); i++)
        Joystick[0].setButton(i, shift[1].state(i));            // just press or release the button
      }
    if (shift[2].update()) {
        for (int i = 0; i < shift[2].getDataWidth(); i++)
        Joystick[0].setButton(i, shift[2].state(i));            // just press or release the button
      }
      delay(10);
    */
    }

body:
Each `ShiftIn` instance handles just one connection. You need to make multiple instances.

    ShiftIn shift1<3>;
    ShiftIn shift2<3>;
    ShiftIn shift3<3>;

Then you `begin` each of them:

    void setup() {
        shift1.begin(8, 9, 11, 12);
        shift2.begin(7, 6, 5, 4);
        shift3.begin(3, 2, 1, 0);
        ... etc ...
    }

Each `shiftx` is a completely separate entity. You can just repeat your block of code for each `shift` object:

    if (shift1.update()) {
        for (int i = 0; i < shift1.getDataWidth(); i++)
        Joystick[0].setButton(i, shift1.state(i));
    }

    if (shift2.update()) {
        for (int i = 0; i < shift2.getDataWidth(); i++)
        Joystick[1].setButton(i, shift2.state(i));
    }

    if (shift3.update()) {
        for (int i = 0; i < shift3.getDataWidth(); i++)
        Joystick[2].setButton(i, shift3.state(i));
    }

You could arrange the `ShiftIn` objects into an array like you do with your `Joystick` objects and then loop through them, but that is pretty pointless for just three of them.


sender: user

message:
Controlling 16x2 LCD backlight (I2C module)

I've installed an [I2C module][1] on my [16x2 LCD][2] so i don't have access to all those LCD pins to control the backlight LED.

**BUT** there is a 100 ohm smd resistor in series with anode of the backlight LED, i want to remove the resistor and use Arduino PWM to control the backlight or i can just replace that resistor with a 330 ohm or a 1K resistor.

[![][3]][3]

*Red box showing the resistor and blue box showing the Jumper.*

Also I2C module itself have a jumper for LED backlight which also goes to that resistor...

Just wanted to ask here and make sure it is going to work before doing any modification to the LCD.

which way is better? is it going to work?
___
**UPDATE:** *i used Arduino PWM and a 2n2222 transistor and was able to successfully control the backlight brightness via jumper pins of I2C module.*

  [1]: http://www.mantech.co.za/datasheets/products/lcd2004-i2c.pdf
  [2]: https://components101.com/16x2-lcd-pinout-datasheet
  [3]: https://i.stack.imgur.com/0qfa7.jpg

sender: assistant

body:
It's hard to tell from the limited information, but chances are the "backlight jumper" mentioned in passing in the datasheet can be simply removed.  This will then give you two pins.  One will connect to pin 3 of the IO expander, and the other will connect to the back light anode itself.

Which is which you will have to discover for yourself.  One of them will have the 100Ω resistor in line with it as well.

If you can't see the tracks (some black boards are hard to make them out) then you should get a digital multimeter and set it to continuity mode and probe the pins to see where they lead.

Once you have identified which pin is which you can connect the one that goes to the back light to your Arduino and drive it with PWM.


message:
I cannot open/write to dataFile SD shield in mySketch but have no problem with Datalogger example sketch from the SD library...?

Hello Arduino Community

I am collecting data and attempting to log it on to a Deek Robot SD shield via a Mega.

I have the data  in a dataString which I can Serial.print to the monitor but would like to log it to an SD card instead. When I run the the Datalogger example sketch from the SD library I can see the data and access the datalog file from the SD card (as per point of the example) but when I try to cross-pollinate the example with mySketch the debugging message

> error opening datalog.txt

is all I get.

I've uploaded the sketch, apologies it is pretty long, there's some adc stuff going on, the call for the data file open and write etc starts on line 200 and ends on 212.

I've tried positioning the datafile functions in different places in the code, using other libraries, reading forum posts but I am getting nowhere. if anyone could point out what I'm doing wrong I would be eternally grateful.

Cheers,
Michael
<!-- language-all: lang-cpp -->
```
//!!!change this to name of sketch!!!!
#define SKETCH_VERSION "SD for loop array test"

//include relevant libraries
#include <EnableInterrupt.h>
#include <SPI.h>
#include <SD.h>

//globally define pins
#define BUSY 3    //purple*
#define RD 4      //yellow* RD+CS tied together
#define RESET 5   //grey*
#define CONVST 6  //green* CONVSTA+CONVSTB soldered together on the board
#define RANGE 7   //blue*   *not permanent - double check!!!*

#define DB0 38
#define DB1 39
#define DB2 40
#define DB3 41
#define DB4 42
#define DB5 43
#define DB6 44
#define DB7 45
#define DB8 46
#define DB9 47
#define DB10 48
#define DB11 49
#define DB12 50
#define DB13 51
#define DB14 52
#define DB15 53

byte statusLed       = 13;
byte sensorPin1       = 10;
byte sensorPin2       = 11;
byte sensorPin3       = 12;

int sensorValue[8];
int rawData[16];

//change the size  of these arrays to match the amount of channels being read by the ADC
int adcChannel[5];
int adcData[5];
int channelCount=5;

volatile byte pulseCount1;
volatile byte pulseCount2;
volatile byte pulseCount3;

int pulses[3];

// cs pin for sd-shield *NB 53 for Mega
const int chipSelect = 53;

unsigned long oldTime;

void setup() {             //set up the hardware

  Serial.begin(9600);
  //sd card.....
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  enableInterrupt(BUSY, bitBang, FALLING);

  oldTime            = 0;

  pinMode(DB0, INPUT_PULLUP);
  pinMode(DB1, INPUT_PULLUP);
  pinMode(DB2, INPUT_PULLUP);
  pinMode(DB3, INPUT_PULLUP);
  pinMode(DB4, INPUT_PULLUP);
  pinMode(DB5, INPUT_PULLUP);
  pinMode(DB6, INPUT_PULLUP);
  pinMode(DB7, INPUT_PULLUP);
  pinMode(DB8, INPUT_PULLUP);
  pinMode(DB9, INPUT_PULLUP);
  pinMode(DB10, INPUT_PULLUP);
  pinMode(DB11, INPUT_PULLUP);
  pinMode(DB12, INPUT_PULLUP);
  pinMode(DB13, INPUT_PULLUP);
  pinMode(DB14, INPUT_PULLUP);
  pinMode(DB15, INPUT_PULLUP);

  pinMode(RESET, OUTPUT);
  pinMode(CONVST, OUTPUT);
  pinMode(RD, OUTPUT);
  pinMode(RANGE, OUTPUT);
  pinMode(BUSY, INPUT);

  //reset ADC to begin conversion
  digitalWrite(RESET, HIGH);
  delayMicroseconds(10);
  digitalWrite(RESET, LOW);

  digitalWrite(CONVST, LOW);
  digitalWrite(RD, HIGH);
  digitalWrite(RANGE, LOW);
  digitalWrite(BUSY, LOW);

  delayMicroseconds(100);

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

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

  pinMode(sensorPin2, INPUT_PULLUP);
  digitalWrite(sensorPin2, HIGH);

  pinMode(sensorPin3, INPUT_PULLUP);
  digitalWrite(sensorPin3, HIGH);

  pulseCount1        = 0;
  pulseCount2        = 0;
  pulseCount3        = 0;

  oldTime            = 0;

  // the hall effect sensors are configured to trigger on a FALLING state change
  // (transition from HIGH state to LOW state)
  enableInterrupt(sensorPin1, pulseCounter1, FALLING);
  enableInterrupt(sensorPin2, pulseCounter2, FALLING);
  enableInterrupt(sensorPin3, pulseCounter3, FALLING);

  //this prints the name of the sketch !!!read line 1!!!
  Serial.print("sketch version: ");
  Serial.println(SKETCH_VERSION);

}

void loop() {
  //Serial.print("hello");
  //change this value to preferred sampling rate
  if ((millis() - oldTime) == 1000) {

    oldTime = millis();

    //Serial.print(millis());
    //Serial.print("\t");

    //tell ADC to start read (converting analogue input to digital output)
    delayMicroseconds(10);
    digitalWrite(CONVST, LOW);
    delayMicroseconds(10);
    digitalWrite(CONVST, HIGH);
    //when read-conversion is complete ADC sends the BUSY pin low triggering the bitBang ISR

    //print ADC data from array within the bitBang ISR to a string
    String adcString = "";
    for(int thisChannel=0; thisChannel<channelCount; thisChannel++){
      adcString += String(adcData[thisChannel]);
      adcString += ",";
    }

    //disable interrupt to access current pulse count
    disableInterrupt(sensorPin1);
    disableInterrupt(sensorPin2);
    disableInterrupt(sensorPin3);
    //grab current pulse count and store in a variable
    pulses[0] = pulseCount1;
    pulses[1] = pulseCount2;
    pulses[2] = pulseCount3;
    //reset pulse count
    pulseCount1 = 0;
    pulseCount2 = 0;
    pulseCount3 = 0;
    //enable interrupt and start incrementing pulse count again
    enableInterrupt(sensorPin1, pulseCounter1, FALLING);
    enableInterrupt(sensorPin2, pulseCounter2, FALLING);
    enableInterrupt(sensorPin3, pulseCounter3, FALLING);

    String pulseString = "";
    for(int i=0; i<3; i++){
      pulseString += String(pulses[i]);
      if (i<2) {
        pulseString += ",";
      }
    }

    String dataString = String(adcString + pulseString);
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

 //Serial.println(dataString);

  }
//start again
}

//grabbing ADC data ISR (for n channel)
void bitBang ()  {
  //a for loop to bitbang the values fom the analogue (ADC) channels (maximum 8) sequentially storing them in a variable array (equal to the channels of the ADC)
  for(int thisChannel=0; thisChannel<channelCount; thisChannel++){
  //send ADC read pin low to bitbang the first channel
  digitalWrite(RD, LOW);
  //read the state of the 16 pins and store in a variable
  rawData[0] = digitalRead(DB15);
  rawData[1] = digitalRead(DB14);
  rawData[2] = digitalRead(DB13);
  rawData[3] = digitalRead(DB12);
  rawData[4] = digitalRead(DB11);
  rawData[5] = digitalRead(DB10);
  rawData[6] = digitalRead(DB9);
  rawData[7] = digitalRead(DB8);
  rawData[8] = digitalRead(DB7);
  rawData[9] = digitalRead(DB6);
  rawData[10] = digitalRead(DB5);
  rawData[11] = digitalRead(DB4);
  rawData[12] = digitalRead(DB3);
  rawData[13] = digitalRead(DB2);
  rawData[14] = digitalRead(DB1);
  rawData[15] = digitalRead(DB0);
  //convert into 16bit 2s compliment and store in a variable array
  adcData[thisChannel] = rawData[0] | (rawData[1] << 1) | (rawData[2] << 2) | (rawData[3] << 3) | (rawData[4] << 4) | (rawData[5] << 5) | (rawData[6] << 6) | (rawData[7] << 7) |  (rawData[8] << 8) | (rawData[9] << 9) | (rawData[10] << 10) | (rawData[11] << 11) | (rawData[12] << 12) | (rawData[13] << 13) | (rawData[14] << 14) | (rawData[15] << 15);
  //send ADC pin high to say we have read the first channel
  digitalWrite(RD, HIGH);
  //repeat for n channels
  }
}

//counting pulses ISRs
void pulseCounter1(){
  // Increment the pulse counter
  pulseCount1++;
}
void pulseCounter2(){
  // Increment the pulse counter
  pulseCount2++;
}
void pulseCounter3(){
  // Increment the pulse counter
  pulseCount3++;
}
```

body: The SD card uses SPI for communications.  You appear to be using those pins for some other purpose.  If you want to use the SD card, then you need to choose other pins and let the SD card have 50, 51, 52, and 53.


message:
ESP12E Boot vs SPI

I was wondering how I could overcome the next issue;

My ESP8266 12E is connected as follows:

 - GPIO0 ground if needed to program, vcc otherwise
 - GPIO2 vcc
 - GPIO15 ground

[Bootmodes explained in the this schematic][1]

I also want to connect a MCP3002 to my ESP. However to use SPI I also need the GPIO15 pin to be connected to the Chip Select pin.

[MCP connections explained in this article][2]

----

I tried connecting the GPIO15 pin from the ESP to the CS pin of MCP3002 and connecting ground in between. This did not work though, should I switch/remove the ground after boot somehow?
(Or should I connect it differently?)

  [1]: https://www.circuito.io/blog/programming-esp8266-12e/
  [2]: https://prkl.info/esp8266-mcp3002-driver/

body:
The io 15 is SS if esp8266 is slave. If esp8266 is SPI master, you can choose any free pin as CS of the slave.

----------

The esp8266 arduino boards package SPISlave library examples have a solution for master if esp8266 is slave.

The state of the boot pins is required only at boot. You should wire boot pins over a 10 kOhm resistor to create a pull-up/pull-down which can be override by pin output state to use the pins for devices which are OK with or need pull-up or pull-down, for example momentary switches (buttons).


message:
Wire SlaveReceiver : will the registered function in onRecieve interrupt/conflict with loop block?

I am currently researching on I2C, and I made a configuration that has MasterWriter that transmits data to a SlaveReceiver that will store the data received from Master, into an SD card, and then transmit the same line of data by GPRS onto my back end.

Now the new requirement needs some kind of a caching system, so that if the GPRS failed to transmit, it'll instead save into the SD card under a different filename (the previous step of saving into SD Card is still done but it's for another purpose), so when the GSM signal needed has recovered it'll read the cached/backed-up data, and then transmit the backed-up data. So that means I'll use the loop block (which currently only has one line of delay function).

My question is, will the triggered function "receiveEvent" registered in setup for Wire Slave :

> Wire.onReceive(receiveEvent);

conflict with the ongoing loop block where the system reads the backed-up data and sends the backed-up data?

Here's my SlaveReceiver code :
<!-- language-all: lang-cpp -->

```

#define ONLINE_MODE 1 //  turn on for GSM.
#define CACHE_MODE 1 //   turn on for SD-based caching
#define I2C_MODE 1  //    turn on for I2C mode SDA-SCL

#include <Arduino.h>
#include "Slave_GSM_SD.h"

#if ONLINE_MODE
// Sim900
#include "GSM.h"
SIM900 gprs;
#endif

#if I2C_MODE
#include <Wire.h>
#endif

#if CACHE_MODE
//SD Card
#include <SPI.h>
#include <SD.h>
#define DEBUG_SD 1
#define SD_CS_PIN 4
File cacheFile;
#endif

void setup()
{
    console.begin(9600);
    while (!console);

    #if CACHE_MODE
     //SD Card
    Serial.print(F("Initializing SD card..."));

    if (!SD.begin(SD_CS_PIN)) {
      Serial.println(F("initialization failed!"));
      while (1);
    }
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    cacheFile = SD.open("CACHE.txt", FILE_WRITE);
    Serial.println(F("SD Card initialization done."));
    #endif

    #if ONLINE_MODE
    gprsSetup();
    #endif

    #if I2C_MODE
    Wire.begin(8);                // join i2c bus with address #8
    Wire.onReceive(receiveEvent); // register event
    #endif
    console.println(F("SLAVE GSM SD READY"));

}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
// [Q] : will this interrupt/conflict with loop() if loop is still ongoing?
void receiveEvent(int howMany) {
  #if DEBUG_I2C
  Serial.print(F("available bytes : "));
  Serial.print(howMany);
  Serial.print(F(" or "));
  Serial.println(Wire.available());
  #endif

  #if I2C_MODE
  char jsonData[128]="";
  while (Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character

    int len = strlen(jsonData);
    jsonData[len] = c;
    jsonData[len+1] = '\0';

    #if DEBUG_I2C
    Serial.print(c);         // print the character
    #endif

    if (c == '}'){

      #if CACHE_MODE
      writeToSd(jsonData);
      #endif

      #if ONLINE_MODE
      gprsSequence(jsonData);
      #endif

      #if DEBUG_I2C
      Serial.println(F("SAVING TRIGGERED"));
      Serial.println(jsonData);
      #endif
    }

  }
  #endif
}

void writeToSd(char *jsonToWrite){

  #if CACHE_MODE
  // open the file. note that only one file can be open at a time,
 // so you have to close this one before opening another.
  cacheFile = SD.open("CACHE.txt", FILE_WRITE);
  if (cacheFile) {
    cacheFile.write(jsonToWrite);
    cacheFile.close();
  }

  #if DEBUG_SD
  Serial.println(F(" << "));
  // re-open the file for reading:
    cacheFile = SD.open("CACHE.txt");
    if (cacheFile) {
    Serial.println("CACHE.txt:");

    // read from the file until there's nothing else in it:
    while (cacheFile.available()) {
      Serial.write(cacheFile.read());
    }
      // close the file:
      cacheFile.close();
    } else {
      // if the file didn't open, print an error:
      Serial.println(F("error opening CACHE.txt"));
    }
  #endif
  #endif

}

void loop() {
    // i wanted to code the cached-data sending here
    delay(2000);
}

void gprsSetup() {
  //... cleared for brevity
}

void gprsSequence(char *jsonData) {
    //... cleared for brevity. the point is, this function is to send the jsonData by GPRS
}
```

body:
Generally the `onReceive` callback function is called from an ISR in the `Wire` library. That means, that no other interrupts can be handled during that time. For this reason an ISR always should be as short as possible. Writing to the SD card is a rather long process and it also uses interrupts, so it might block forever, when used in an ISR (though I'm not sure, since I didn't look through the SD library). You should do the SD card stuff outside of the ISR. In the ISR you can receive the I2C message and then set a flag variable, that will tell the code in the `loop()` function, that new data is available and that it can start processing it. That way your ISR stays short and the other operations will not be blocked by it. Do the same with the direct sending of GPRS data.

Also note, that transmitting Serial data inside of an ISR also does not work for the same reason (Serial relies on interrupts). The calls to `Serial.print()` or `Serial.write()` will only fill the libraries internal buffer. The data will get transmitted after the ISR was left. If you try to print/write data to Serial, when the buffer is full, the library will block, until the buffer has again space for sending the data, which will never happen inside the ISR. So you should be cautious with writing Serial inside an ISR. A bit doesn't hurt, but it can get a big problem.

> will the triggered function "receiveEvent" registered in setup for
> Wire Slave `Wire.onReceive(receiveEvent);` conflict with the ongoing
> loop block where the system reads the backed-up data and sends the
> backed-up data?

From the general logic there cannot happen more than 1 specific data operation on the SD card at the same time. If you are currently writing one file, you cannot simply break the transmission through an interrupt and writing another file without breaking things. The transaction has to be completed, or you will fastly corrupt your file system. But, as I wrote above, this isn't really possible either way, because the SD card calls will not work properly inside of an ISR. So just put all the GPRS and SD card code into the `loop()` function and trigger the corresponding code blocks with a flag from the ISR. That way nothing can conflict here.


message:
Connect 20 12v led to an arduino mega

I want to control about 20 leds with an arduino mega.
This leds works with 12v voltage.

I tried to put 20 relays but this solution is not good for me because leds will often blink

I have also tried transistors but it needs to make a pcb.

I am looking for a solution without having to create a pcb

Any idea ?

Thanks

body:
You can use the commonly available L298N module to drive four of your LEDs with each module. That means you would need five of them.
[![L298N module][1]][1]
Those modules are suitable for driving either one stepper motor, two DC motors (in both directions), or four "unidirectional" loads such as your LEDs.

The input can be connected directly to your MEGA, but you may need additional series resistors depending on the LED you use (though this likely does not apply for LEDs specified as "12V").

There are also LED driver eval boards available which may suit your needs:
https://www.digikey.de/product-detail/de/adafruit-industries-llc/1455/1528-1019-ND/4990768

  [1]: https://i.stack.imgur.com/15EKF.jpg


body:
The ULN2803 is a chip with 8 darlington transistors in it designed for driving higher voltage, low-ish current, loads like this.  With 3 of them you have 24 channels to drive your LEDs.

You can get them on a breakout board quite easily, or as a DIP chip for working with breadboards.


body: Try s MOS- FET transistor.  Its not expensive and easy to drive.  Can be directly connected to the Arduino.  Look for standard circuit diagrams.  1 P- Mos Fet and 1 Resistor per channel,  esch can drive several Amperes st 12V...


body:
Three TPIC6B595 shift registers, controlled by 3 pins from the Mega, can do this easily. Shift in 3 bytes with on/off state of the LEDs.
Can sink 150mA per output from 12V source.  The LEDs need current control, from simple resistor for 20mA loads, to a constant current driver per LED for higher current LEDs.

I used them to sink current from 12V for the LED strings in this display. The small digits needed ~ 20mA per segment, the larger digit is really 2 groups of 3 LEDs, drawing about 40mA per segment. One shift register per digit.

https://www.youtube.com/watch?v=6HZ0Mr51jUY


message:
How to Run Stepper motor through Serial Communication

I am trying to run a Stepper motor from my c++ application, from which I sent commands but its not running not sure why would it not run, outside serial check it run but inside serial check it not run.

Here is my code, not sure what am doing wrong, my first time with Arduino.
<!-- language-all: lang-cpp -->

    #include <AccelStepper.h>

    #define BAUD 9600

    // CNC Shield V3  Step and Dir pins on Mega 2560
    #define step_pin_x 2
    #define dir_pin_x 5
    #define MOTOR_X_ENABLE_PIN 8
    // Drive A4988
    #define motorInterfaceType 1

    AccelStepper stepper_X = AccelStepper(motorInterfaceType, step_pin_x, dir_pin_x);

    void setup() {
      Serial.begin(BAUD);
      pinMode(53, OUTPUT);   // for red led it pin # 53
      pinMode(MOTOR_X_ENABLE_PIN, OUTPUT);  // for X stepper motor

        stepper_X.setMaxSpeed(1000);
        stepper_X.setSpeed(500);
    }

    void loop() {
        String input;
      //If any input is detected in arduino
      if(Serial.available() > 0){
        //read the whole string until '\n' delimiter is read
        input = Serial.readStringUntil('\n');

        if (input.equals("ON")){
           digitalWrite(53, HIGH);   // Turn ON RED LED
           stepper_X.runSpeed();      // Suppose to run stepper motor .. but not working
           Serial.println("X Motors:: "+input);

        }else if (input.equals("OFF")){
           stepper_X.stop();
           digitalWrite(53, LOW);    // Turn OFF RED LED
           Serial.println("X Motors:: "+input);
        }

      }else{
      //  stepper_X.runSpeed();      // if uncommented stepper motor will run
      }
    }

**Update**
so it seems its code blocking issues

i update my code according to tut : https://majenko.co.uk/blog/reading-serial-arduino

        char buf[80];

        int readline(int readch, char *buffer, int len) {
            static int pos = 0;
            int rpos;

            if (readch > 0) {
                switch (readch) {
                    case '\r': // Ignore CR
                        break;
                    case '\n': // Return on new-line
                        rpos = pos;
                        pos = 0;  // Reset position index ready for next time
                        return rpos;
                    default:
                        if (pos < len-1) {
                            buffer[pos++] = readch;
                            buffer[pos] = 0;
                        }
                }
            }
            return 0;
        }

    void loop() {
       if (readline(Serial.read(), buf, 80) > 0) {
       if(strcmp("n", buf) == 0){
              digitalWrite(53, HIGH);
             stepper_X.setMaxSpeed(1000);
             stepper_X.setSpeed(500);
              stepper_X.runSpeed();
              Serial.print("All Motors:: ");
              Serial.print(buf);

            }
        }
    }

now its working ok

**Update 2 :** c++ sending command via Serial

        std::string input_command = "ON";
        //Creating a c string
         char *c_string = new char[input_command.size() + 1];
         //copying the std::string to c string
         std::copy(input_command.begin(), input_command.end(), c_string);
         //Adding the delimiter
         c_string[input_command.size()] = '\n';

    // using this serial lib : https://github.com/manashmndl/SerialPort
       writeSerialPort(c_string, MAX_DATA_LENGTH);

body:
Per [the documentation of the AccelStepper’s `runSpeed()`
method][runSpeed]:

> You must call this as frequently as possible, but at least once per
> step interval,

It appears the AccelStepper library is not compatible with blocking
code. Not a big deal, blocking code is almost always bad practice
anyway. However, `Serial.readStringUntil()` is a blocking function: it
will prevent the program from doing any useful work.

You have to [read the serial port in a non-blocking fashion][serial],
use the commands to set the motor speed, and always call `runSpeed()` as
frequently as possible.

[runSpeed]: http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#aa4a6bdf99f698284faaeb5542b0b7514
[serial]: https://majenko.co.uk/blog/reading-serial-arduino


message:
ESP - Nodemcu amica - attachInterrupt crash program

I get new boards from the shop but they are little different from the previous version. I got software what works ok on Nodemcu lolin v3 now I get Nodemcu Amica what is almost same board but if I got attachInterrupt function in the program it crashes immediately.

        attachInterrupt(6, bowlingCall, RISING);
    //attachInterrupt(digitalPinToInterrupt(D1), statekCall, RISING);

I try different pins but not change. I debug all program(comment all out and left just attachInterrupt and it crashes again).

        ets Jan  8 2013,rst cause:2, boot mode:(3,6)

    load 0x4010f000, len 1384, room 16
    tail 8
    chksum 0x2d
    csum 0x2d
    v8b899c12
    ~ld

The board cycle in the reboot sequence, even serial output do not work ok. Why did esp crash at attachInterupt on this board?

body:
thanks @Juraj.

Ok, so all you need is rewrite all your interrupt function.
For example:

    void getStatusFromMaster()

to

    void ICACHE_RAM_ATTR getStatusFromMaster()


message:
Why is the IDE not able to find the board despite it being clearly seen and selected?

i'm having an odd problem where despite having the correct port selected 3 times i'm still getting an error as shown below: [![error][1]][1] message:

    Arduino: 1.8.9 (Windows 10), Board: "Adafruit Feather M0, Arduino, Off"

    Sketch uses 20876 bytes (7%) of program storage space. Maximum is 262144 bytes.
    Atmel SMART device 0x10010005 found
    Device       : ATSAMD21G18A
    Chip ID      : 10010005
    Version      : v2.0 [Arduino:XYZ] Mar  5 2016 17:46:52
    Address      : 8192
    Pages        : 3968
    Page Size    : 64 bytes
    Total Size   : 248KB
    Planes       : 1
    Lock Regions : 16
    Locked       : none
    Security     : false
    Boot Flash   : true
    BOD          : true
    BOR          : true
    Arduino      : FAST_CHIP_ERASE
    Arduino      : FAST_MULTI_PAGE_WRITE
    Arduino      : CAN_CHECKSUM_MEMORY_BUFFER
    Erase flash
    done in 0.832 seconds

    Write 21164 bytes to flash (331 pages)

    [=====                         ] 19% (64/331 pages)
    [===========                   ] 38% (128/331 pages)
    [=================             ] 58% (192/331 pages)
    [=======================       ] 77% (256/331 pages)
    [============================= ] 96% (320/331 pages)
    [==============================] 100% (331/331 pages)
    done in 0.128 seconds

    Verify 21164 bytes of flash with checksum.
    Verify successful
    done in 0.016 seconds
    CPU reset.
    Couldn't find a Board on the selected port. Check that you have the correct port selected.  If it is correct, try pressing the board's reset button after initiating the upload.

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

  [1]: https://i.stack.imgur.com/T0jFH.png

body:
The SAMD boards connect to computer over native USB support of the MCU. The handling of the USB is done by Arduino core functions linked at build to your sketch.

A consequence of using the native USB port is, if your sketch has a problem, it influences the USB communication. In this case you can activate the bootloader to handle the USB port and the upload. It is done by **double clicking the reset button** on board.


message:
How to NOT repeat a piece of code again and again?

I have a VERY long code:

> Sketch uses 30468 bytes (92%) of program storage space. Maximum is
> 32768 bytes.

I've been trying to reduce it's size so i can write more code, one of my main part of code which repeated many times in switch cases or in if statements is related to de-bouncing the buttons.

Here's a piece of my code as an example:

      case 12:
        if ((millis() - millistimer) > BounceD) {
          if (receivedValue == RFb) {
            magnetDistance += 5;
            millistimer = millis();
            receivedValue = 0;
          }
        }
        if ((millis() - millistimer) > BounceD) {
          if (receivedValue == RFd) {
            magnetDistance -= 5;
            millistimer = millis();
            receivedValue = 0;
          }
        }
        break;

The de-bouncing actions happens in each and every case and for each and every button.

There's two buttons which in each `case` increase/decrease different values.

How to avoid repeating the de-bouncing action for every button?

___

**EDIT:**

The `recievedValue` is updated via RC buttons value once any button is pressed on the remote.

body:
In the short example of above, first find out what is a duplicate (the two outer `if` statements including their body), than the differences:

- Rfb versus Rfd
- +5 versus -5

Than make a function for the duplicated code, and turn all differences into a parameter (I don't know the type of Rfd, so I take an int for it).

You will get:

    case 12:
      processButton(&Rfb,  5); // Offset magnet distance by +5
      processButton(&RFd, -5); // Offset magnet distance by -5
      break;

      ...

    void processButton(int* rf, int diff)
    {
      if ((millis() - millistimer) > BounceD) {
        if (receivedValue == *rf) {
          magnetDistance += diff;
          millistimer = millis();
          *rf = 0;
        }
      }
    }

Note that if `magnetDistance` and `millistimer` are local variables you also have to pass them (as pointer to change the value), if they are globals you can keep the code as is above.

**UPDATE**

The way parameter works is as follows. E.g.

    processButton(Rfb,  5);

Will call the following function:

    void processButton(int rf, int diff)

Where value rf will be Rfb, and diff will be 5 (+5).

Thus when `magnetDistance += diff;` is executed, diff will be +5 and magnetDistance will be increased with +5. In the next call, magnetDistance will be -5 and thus will be subtracted.

**UPDATE 2**

To change a variable, you have to pass it as pointer, otherwise the (copied) parameter value will be changed and not return its value to the called function. So you have to give the parameter as an address (& operator), and use -> instead of . to get to the value.


message:
How do I send MIDI properly with ESP8266?

So, I've finally able to send and receive MIDI using Arduino.

My next thing to do was sending 5 pin MIDI to rtpMIDI, and vice versa, using ESP8266, but so far I can't even send MIDI correctly.
So far, I used this library, and it send midi without issues with Arduino Mega. But using Wemos D1, strange thing happens.

[![enter image description here][1]][1]
this is output of MIDI OX. Pretty sure I wasn't sending MIDI CC.

Here's the code so far :

    #include <MIDI.h>

     // Created and binds the MIDI interface to the default hardware Serial port
     MIDI_CREATE_DEFAULT_INSTANCE();

     void setup()
     {
         MIDI.begin(MIDI_CHANNEL_OMNI);  // Listen to all incoming messages
     }

     void loop()
     {
         // Send note 42 with velocity 127 on channel 1
         MIDI.sendNoteOn(42, 127, 1);

         // Read incoming messages
         MIDI.read();
     }

UPDATE : Here goes the settings.

[![enter image description here][2]][2]

Any reason why this happens? Please help me. Thanks!

Schematics :

Basically I just change the Arduino to Wemos D1 Uno.
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/i5EX0.png
  [2]: https://i.stack.imgur.com/eWgcu.png
  [3]: https://i.stack.imgur.com/jqPZz.png

body:
NOTE : Probably not the answer you're looking for, but it works for me.

Solution : Move the jumper from 5V to Vin.

Why? I don't know. It just works.

Please notice that this is Wemos D1 Uno, which has adaptor input, which can receive 9-24V.

If you're going to use the adaptor, IT MAY BROKE YOUR MIDI DEVICE!

As far as I know, Vin stands for Voltage Input, and everything from the adaptor is routed there. That means if you use 24v adaptor, Vin is 24v!

I'm only planning to use USB as power supply, so yeah. it works for me.

If you're going to use Vin with external power supply, please use voltage regulator to 5v. Better safe than sorry.

Anyway, since I'm planning to use 6N137 to receive MIDI also on this board, here goes :

> Input voltages greater than 7 V must be avoided to preclude damage to
> the gate oxide of the input stage. This damage is not necessarily
> permanent, but will adversely affect the expected lifetime of the
> circuit. The gate oxide of AHC devices is only 200 Å thick. An input
> voltage of 7 V corresponds to a field strength over the gate oxide of
> 350 kV/cm. Although breakdown of the oxide is expected only at input
> voltages above 10 V, electrons tunnel increasingly into the gate oxide
> at field strengths greater than 350 kV/cm, influencing characteristics
> of the transistors and causing failure.

Source : this question on electronics stackexchange.


message:
Refactoring bad design?

Could someone help me how to refactor old very complex code ?

Original used just setup and everything else was in single ISR.
But as it was bigger and bigger, code is quite slow and quite random sometimes, even PC emulator did not helpped much (probably some long operations like printing are sometimes interrupted by next interrupt depending on analog values, buttons, etc.).

Is there any guide how to maintain such a project or is there only way out start again from scratch ?

As there are few important regulations also event queue would be needed, but not sure if there is any pattern or a template to start from in case of restart. A-Star 32U4 Micro has <32kB flash and code is hard to fit in yet (there are also big fonts).

*Example of font unpack code, but hope this part is quite ok:*

    void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
      uint16_t color, uint16_t bg, uint8_t size) {
    ...
        uint8_t blockSize = 0;
        if(packed) blockSize = pgm_read_byte(&bitmap[bo++]); // for first char pick 1st bit array only
        BitStreamsReader bitStream(&bitmap[bo++], packed?blockSize:0); // ptr, blockSize(if packed)
        BitXorBuffer rowXorBuf(w); // row XOR buffer (each row is XORed with)
        bool chk;
        for(yy=0; yy<h; yy++) {
            rowXorBuf.rewind();
            for(xx=0; xx<w; xx++) {
                chk = bitStream; // read 1b
                if(packed) chk = rowXorBuf.xorMove(chk); // xor with XOR buffer
                if(chk) {
                    if(size == 1) {
                        writePixel(x+xo+xx, y+yo+yy, color);
                    } else {
                        writeFillRect(x+(xo16+xx)*size, y+(yo16+yy)*size,
                            size, size, color);
                    }
                }
            }
        }
    ...

    class BitStreamsReader {
    public:
     BitStreamsReader(uint8_t *arr, unsigned int maxSize) {
      blockSize = maxSize;
      bitMask = 0x80;
      bytePtr = arr;
      zerosCount = 0;
      remainingBits = 0;
      markBitInit();
     }
     operator bool() {
      if(!blockSize) { // unpacked stream
       bool retVal = !!(pgm_read_byte(bytePtr) & bitMask);
       next();
       return retVal;
      } else if(remainingBits) {
       bool retVal = !!(pgm_read_byte(bytePtr) & bitMask);
       next();
       if(!--remainingBits) {
        markBitInit();
       }
       return retVal;
      } else if(zerosCount) {
       if(!--zerosCount) {
        markBitInit();
       }
       return 0;
      }
      return 0; //throw "??";
     }
    private:
     void markBitInit() {
      if(blockSize) {
       if(pgm_read_byte(bytePtr) & bitMask) {
        remainingBits = blockSize;
       } else {
        zerosCount = blockSize;
       }
       next();
      }
     }
     void next () {
      if(bitMask == 0x01) {
       bitMask = 0x80;
       bytePtr++;
      } else {
       bitMask >>= 1;
      }
     };
     uint8_t *bytePtr, bitMask, zerosCount, remainingBits, blockSize;
    };

    class BitXorBuffer {
    public:
     BitXorBuffer(int bufSize) {
      bufSize = bufSize/8+!!(bufSize&7);
      bitBuf = new uint8_t[bufSize];
      memset(bitBuf, 0, bufSize);
      rewind();
     }
     ~BitXorBuffer() {
      delete[] bitBuf;
     }
     void rewind() {
      bitMask = 128;
      bytePtr = bitBuf;
     }
     bool xorMove(bool by) {
      if(bitMask & *bytePtr) by ^= true;
      *bytePtr |= bitMask;
      if(!by) {
        *bytePtr ^= bitMask;
      }
      nextBit();
      return by;
     }
    private:
     void nextBit() {
      if(bitMask > 1) {
       bitMask >>= 1; // move bit in XOR buffer
      } else {
       bitMask = 128;
       bytePtr++;
      }
     }
     uint8_t *bytePtr, *bitBuf, bitMask;
    };

body:
I will try to answer your question as good as possible, though it is quite broad.

To my knowing there is no ONE design pattern or template, that fit's all cases. But depending on the actual functions of your code you can go different ways using libraries (which are somewhat like templates in this sense).

You can get easy multitasking by using libraries like [FreeRTOS][1]. You might even find a compatible version of SafeRTOS, a sibling of FreeRTOS, which has a bigger focus on security. Though the whole RTOS thing might not be right for you and it needs your code to be mostly rewritten/redesigned.

Depending on what ISRs are used and what they are for, you might really need to use interrupts to let the device react immediately. In that case you basically have not choice, but to refactor the whole code as described in the comments (moving as much code as possible to the main loop, making the ISR drastically smaller). For this here some general advice:

- First make a graph of the devices function as it should be. Identify code portions that have a common function, but them into blocks, draw arrows between the blocks to show, how they are connected logically. Then identify which portions are really time critical and what the time contrains are (e.g. Do you need the device to react to an event within a few clock cycles or is it ok, if the reaction comes a few us or ms later?). Mark how often the involved events occur at average and at maximum.
- Now look at the code blocks directly. Which of them need interrupts to work and what happens with them, if interrupts are turned of during their operation (since - as you already identified - reactivating interrupts inside an ISR can get very messy). For example with interrupts off, Serial prints will not be send directly (because this relies on interrupts). Instead the libraries buffer will be filled. When the buffer is already full, a print will wait for the buffer to empty a big (which does not happen with interrupts off).
- Move all code, that is not really time critical, into an if statement in the main loop function. The if statement should be activated by a flag, that would be set in the ISR (be sure to declare it volatile).
- Make sure, that there is nothing blocking in your code (no `delay()`, no waiting for an event in an infinite loop). That also might require serious refactoring, but it's important if you want a fast reaction also outside of the ISR. You might want to look into Finite State Machines for this (they are quite easy to implement and a very powerful construct).
- Keep debug prints small, so that it cannot mess up your timing.
- Lastly: Make some documentation. That is mostly reglected, because it is not that rewarding, but it can save many hours for the next programmer, that needs to maintain your code.

That might seem very time consuming, difficult and not like the comprehensive guide you were looking for. That's the reason, why maintaining legacy code is mostly a real pain in the a*** and does cost companies a lot of money.

At one point or another the technical debt has to be paid. The inventor of the code clearly didn't (or he/she would't have written an ISR this big), so now you will most likely have to go the hard way.

  [1]: https://create.arduino.cc/projecthub/feilipu/using-freertos-multi-tasking-in-arduino-ebc3cc


message:
16/2 arduino I2C lcd display not lighting up?

I am working with an I2C lcd display with an arduino uno board I have connected the gnd pin to gnd of arduino uno and the vcc pin to 5V of arduino uno and the display is not even lighting up there is only a red led lighting up on the back so I tryed connecting the rest of the pins and run a code to detect the i2c display and it worked successfully I got the adress but the lcd did not light up. The lcd display is a new one I bought yesterday here are the pictures:

https://photos.app.goo.gl/x9QPAWig98yLg4DW9

The script I tryed to display text was this one with the [NewLiquidCristal] [1] library:

    //Libraries
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>

    LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the
    LCD I2C address, if it's not working try 0x27.

    void setup(){
    lcd.begin(16,2);   // iInit the LCD for 16 chars 2 lines
    lcd.backlight();   // Turn on the backligt (try lcd.noBaklight() to turn it
    off)
    lcd.setCursor(0,0); //First line
    lcd.print("I2C LCD Tutorial");
    lcd.setCursor(0,1); //Second line
    lcd.print("*Ardumotive.com*");
    }

Here is the model nmber of the I2C: PCF8574A And the lcd is a QAPASS Ui also I don't have a spec sheet and the LCD seems to show empty chars when rotating the pot.
  [1]: http://www.ardumotive.com/uploads/1/2/7/2/12726513/lcd_i2c_16x2_tutorial.zip

body:
Try this:

    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>

    // LiquidCrystal_I2C lcd(0x27, 16, 2);
    // OR
    LiquidCrystal_I2C lcd(0x3F, 16, 2);

    void setup(){
    lcd.begin();
    lcd.backlight();
    lcd.setCursor(5,0);
    lcd.print("TA DAA...!");
    }
    void loop{
    // do nothing here
    }

If that didn't work probably your LCD have a different address than `0x27` which in that case you should run a I2C scanner to show you the addresses of I2Cs that connected to your Arduino:

    #include <Wire.h>
    // I2C scanner

    void setup()
    {
      Wire.begin();

      Serial.begin(9600);
      Serial.println("\nI2C Scanner");
    }

    void loop()
    {
      byte error, address;
      int nDevices;

      Serial.println("Scanning...");

      nDevices = 0;
      for(address = 1; address < 127; address++ )
      {
        // The i2c_scanner uses the return value of
        // the Write.endTransmisstion to see if
        // a device did acknowledge to the address.
        Wire.beginTransmission(address);
        error = Wire.endTransmission();

        if (error == 0)
        {
          Serial.print("I2C device found at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.print(address,HEX);
          Serial.println("  !");

          nDevices++;
        }
        else if (error==4)
        {
          Serial.print("Unknow error at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.println(address,HEX);
        }
      }
      if (nDevices == 0)
        Serial.println("No I2C devices found\n");
      else
        Serial.println("done\n");

      delay(5000);           // wait 5 seconds for next scan
    }

Check the jumper behind the I2C module (plug it out and in again).

Check the voltage of LED using a multimeter if there's no voltage there, *maybe* it's just a "bad LCD" try replacing it.


message:
Float to String Convert in Udp.write() in esp8266

I want to convert float value to String for send **Udp.Write()**
 method
 and receive another side (esp) with **Udp.read()**
and
Copy in the one Variable for use ..

**please** help me
**Thanks for every answer ^__^**

code :

    void loop () {
        int signal = analogRead (A0) ;
        float Adc = (signal * 3.3) / 4096 ;
        Udp.beginPacket ({192,168,4,1} , 1234) ;
        Udp.write ( " please help me fill this section ") ;
        Udp.endPacket () ;
    }

---

*i have one more problom . . .*

*and in the other side:*

i want take the**Adc** value from **esp1** and **convert char to float** for **Dac**

(*digital analog converter*) with *MCP4725* ..

** i just need put in float value of Adc in a variable for convertation use ..**

*code*:

**void loop ( ) {**

    int noBytes = Udp.parsePacket();

    String received_command = "";

    if ( noBytes ) {

      Udp.read(packetBuffer,noBytes);

      for (int i=1;i<=noBytes;i++){

      received_command += char(packetBuffer[i - 1]);
    }

    Serial.print("packaet receive: ");

    Serial.println(received_command);

    float Adc_value_received = float(received_command); //*helpppp please char-to-float convert*

  **}**

*thanks from everyone* ^__^

body:
The Arduino String class can be used to convert to a character string.

    void loop () {
        int signal = analogRead (A0) ;
        float Adc = (signal * 3.3) / 4096 ;
        String msg = String(Adc, 3);

        Udp.beginPacket ({192,168,4,1}, 1234) ;
        Udp.write(msg.c_str());
        Udp.endPacket () ;
    }


message:
Writing to sd card with a sampling rate 50ms or less? I have a sketch that writes to sd every 1s but jams at faster sampling rates. Please help?

My code below reads data from an ADC and 3 digital pins via a Mega and prints to an SD Shield (Deek Robot). I want to be able to read the data every 50ms (20ms ideally). I can't get below 250ms.

I've read countless forum posts regarding the same issue and understand that I need to create 2x 512 byte buffer, store data to one while the other is being written to the SD card. A forum post mentioned using the Adafruit GPS library for an example of double-buffering but I can't seem to find it. Another suggests changing the internal buffer from 64bytes to 256bytes in hardwareserial.cpp but I can't even navigate to it on my w***ows laptop.

I've run dataString.Length and the max length is 38 for the 8 columns of data, plus a long (for recording ms) another byte for the "\t" and 3 bytes of headroom = 46bytes in all, round it up to 50bytes/sample at a 50ms sampling rate is 1000bytes/second. Darn it, I forgot to add the separating-commas between the columns = plus another 7 bytes; call it 55 in total = 1100bytes/second. I know it can be done but I can't do it; not at my current knowledge/skill level.

Thank you in advance for your help.
<!-- language-all: lang-cpp -->
```
//include relevant libraries
#include <EnableInterrupt.h>
#include <SPI.h>
#include <SD.h>

//globally define pins
#define BUSY 3    //purple*
#define RD 4      //yellow* RD+CS tied together
#define RESET 5   //grey*
#define CONVST 6  //green* CONVSTA+CONVSTB soldered together on the board
#define RANGE 7   //blue*   *not permanent - double check!!!*

#define DB0 22
#define DB1 23
#define DB2 24
#define DB3 25
#define DB4 26
#define DB5 27
#define DB6 28
#define DB7 29
#define DB8 30
#define DB9 31
#define DB10 32
#define DB11 33
#define DB12 34
#define DB13 35
#define DB14 36
#define DB15 37

//byte statusLed       = 13;
byte sensorPin1       = 38;
byte sensorPin2       = 40;
byte sensorPin3       = 42;

int sensorValue[8];
int rawData[16];
//change the size  of these arrays to match the amount of channels being read by the ADC
int adcChannel[5];
int adcData[5];
int channelCount=5;

volatile byte pulseCount1;
volatile byte pulseCount2;
volatile byte pulseCount3;

int pulses[3];

// cs pin for sd-shield *NB 53 for Mega
const int chipSelect = 53;
// SCK 52
// MISO 50
// MOSI 11

unsigned long oldTime;

void setup() {             //set up the hardware

  Serial.begin(9600);
  //sd card.....
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  enableInterrupt(BUSY, bitBang, FALLING);

  oldTime            = 0;

  pinMode(DB0, INPUT_PULLUP);
  pinMode(DB1, INPUT_PULLUP);
  pinMode(DB2, INPUT_PULLUP);
  pinMode(DB3, INPUT_PULLUP);
  pinMode(DB4, INPUT_PULLUP);
  pinMode(DB5, INPUT_PULLUP);
  pinMode(DB6, INPUT_PULLUP);
  pinMode(DB7, INPUT_PULLUP);
  pinMode(DB8, INPUT_PULLUP);
  pinMode(DB9, INPUT_PULLUP);
  pinMode(DB10, INPUT_PULLUP);
  pinMode(DB11, INPUT_PULLUP);
  pinMode(DB12, INPUT_PULLUP);
  pinMode(DB13, INPUT_PULLUP);
  pinMode(DB14, INPUT_PULLUP);
  pinMode(DB15, INPUT_PULLUP);

  pinMode(RESET, OUTPUT);
  pinMode(CONVST, OUTPUT);
  pinMode(RD, OUTPUT);
  pinMode(RANGE, OUTPUT);
  pinMode(BUSY, INPUT);

  //reset ADC to begin conversion
  digitalWrite(RESET, HIGH);
  delayMicroseconds(10);
  digitalWrite(RESET, LOW);

  digitalWrite(CONVST, LOW);
  digitalWrite(RD, HIGH);
  digitalWrite(RANGE, LOW);
  digitalWrite(BUSY, LOW);

  delayMicroseconds(100);

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

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

  pinMode(sensorPin2, INPUT_PULLUP);
  digitalWrite(sensorPin2, HIGH);

  pinMode(sensorPin3, INPUT_PULLUP);
  digitalWrite(sensorPin3, HIGH);

  pulseCount1        = 0;
  pulseCount2        = 0;
  pulseCount3        = 0;

  oldTime            = 0;

  // the hall effect sensors are configured to trigger on a FALLING state change
  // (transition from HIGH state to LOW state)
  enableInterrupt(sensorPin1, pulseCounter1, FALLING);
  enableInterrupt(sensorPin2, pulseCounter2, FALLING);
  enableInterrupt(sensorPin3, pulseCounter3, FALLING);

}

void loop() {

  //change this value to preffered sampling rate
  if ((millis() - oldTime) == 50) {

    oldTime = millis();

    //Serial.print(millis());
    //Serial.print("\t");

    //tell ADC to start read (converting analogue input to digital output)
    delayMicroseconds(10);
    digitalWrite(CONVST, LOW);
    delayMicroseconds(10);
    digitalWrite(CONVST, HIGH);
    //when read-conversion is complete ADC sends the BUSY pin low triggering the bitBang ISR

    //print ADC data from array within the bitBang ISR to a string
    String adcString = "";
    for(int thisChannel=0; thisChannel<channelCount; thisChannel++){
      adcString += String(adcData[thisChannel]);
      adcString += ",";
    }

    //disable interrupt to access current pulse count
    disableInterrupt(sensorPin1);
    disableInterrupt(sensorPin2);
    disableInterrupt(sensorPin3);
    //grab current pulse count and store in a variable
    pulses[0] = pulseCount1;
    pulses[1] = pulseCount2;
    pulses[2] = pulseCount3;
    //reset pulse count
    pulseCount1 = 0;
    pulseCount2 = 0;
    pulseCount3 = 0;
    //enable interrupt and start incrementing pulse count again
    enableInterrupt(sensorPin1, pulseCounter1, FALLING);
    enableInterrupt(sensorPin2, pulseCounter2, FALLING);
    enableInterrupt(sensorPin3, pulseCounter3, FALLING);

    String pulseString = "";
    for(int i=0; i<3; i++){
      pulseString += String(pulses[i]);
      if (i<2) {
        pulseString += ",";
      }
    }

   String dataString = String(adcString + pulseString);
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("dataLog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.print(millis());
    dataFile.print(",");
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    //Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening dataLog.txt");
  }

 //Serial.println(dataString);

  }
//start again
}

//grabbing ADC data ISR (for n channel)
void bitBang ()  {
  //a for loop to bitbang the values fom the analogue (ADC) channels (maximum 8) sequentially storing them in a variable array (equal to the channels of the ADC)
  for(int thisChannel=0; thisChannel<channelCount; thisChannel++){
  //send ADC read pin low to bitbang the first channel
  digitalWrite(RD, LOW);
  //read the state of the 16 pins and store in a variable
  rawData[0] = digitalRead(DB15);
  rawData[1] = digitalRead(DB14);
  rawData[2] = digitalRead(DB13);
  rawData[3] = digitalRead(DB12);
  rawData[4] = digitalRead(DB11);
  rawData[5] = digitalRead(DB10);
  rawData[6] = digitalRead(DB9);
  rawData[7] = digitalRead(DB8);
  rawData[8] = digitalRead(DB7);
  rawData[9] = digitalRead(DB6);
  rawData[10] = digitalRead(DB5);
  rawData[11] = digitalRead(DB4);
  rawData[12] = digitalRead(DB3);
  rawData[13] = digitalRead(DB2);
  rawData[14] = digitalRead(DB1);
  rawData[15] = digitalRead(DB0);
  //convert into 16bit 2s compliment and store in a variable array
  adcData[thisChannel] = rawData[0] | (rawData[1] << 1) | (rawData[2] << 2) | (rawData[3] << 3) | (rawData[4] << 4) | (rawData[5] << 5) | (rawData[6] << 6) | (rawData[7] << 7) |  (rawData[8] << 8) | (rawData[9] << 9) | (rawData[10] << 10) | (rawData[11] << 11) | (rawData[12] << 12) | (rawData[13] << 13) | (rawData[14] << 14) | (rawData[15] << 15);
  //send ADC pin high to say we have read the first channel
  digitalWrite(RD, HIGH);
  //repeat for n channels
  }
}

//counting pulses ISRs
void pulseCounter1(){
  // Increment the pulse counter
  pulseCount1++;
}
void pulseCounter2(){
  // Increment the pulse counter
  pulseCount2++;
}
void pulseCounter3(){
  // Increment the pulse counter
  pulseCount3++;
}
```

body:
Some tips:

- Do not open the open and close the file in every loop sequence (I think you can use the `flush` command to save/update the file.
- Do not save strings, but save the raw data and pulse string. This will take 16 * 2 (raw data + 3 bytes for the pulse data = 35 bytes per 16 samples, meaning 35 bytes/samples * 20 samples/s = 700 bytes (I think your calculation of 1100 bytes is incorrect).
- Try to avoid string, and even more string concatenation. I don't know if this will be the bottleneck, but in any case String operations are expensive and for concatenation there is a chance (or is always the case) that memory needs to be allocated dynamically. Use a string buffer instead.


body:
So it turns out the actual problem was this line of code
`if ((millis() - oldTime) == 50) {`
it needed to be changed to
`if ((millis() - oldTime >= 50) {`

I really appreciate all the help everyone gave me to get to the bottom of it and especially thankful to @Michel for handing some solid advice to someone who isn't in the know.
Hopefully I will be able to repay in kind to another learner one day.
:D


message:
Software I2C - sending data

I'm trying to read a voltage in from a power supply to an Arduino Micro, then send it to an oscilloscope through an I2C (MCP4725). I would use the default pins on the Micro but I want to wire three I2C and the default bus only allows two. As such, I'm trying to use the [SoftI2CMaster library][1]

I've looked through examples and documentation but I can't seem to get it to send any data. I've been successful scanning (from examples) and finding the I2C addresses, so I assume that the trouble is at the end of my code.

Any tips would be greatly appreciated!

    #define SDA_PORT PORTD
    #define SDA_PIN 4 // = A4
    #define SCL_PORT PORTC
    #define SCL_PIN 6 // = A5
    #include <SoftWire.h>

    #define I2C_7BITADDR 0x62 //MCP4725

    SoftWire Wire = SoftWire();

    int aPin;

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

    void loop(void){
      aPin = analogRead(A0); //read in from power supply
      Wire.beginTransmission(I2C_7BITADDR);
      Wire.write(aPin); //send voltage to osc.
      Wire.endTransmission();
    }

  [1]: https://github.com/felias-fogg/SoftI2CMaster

body:
The main problem seems to be, that you are not adhering to the MCP's communication protocol. You just try to directly and only send the pure analog measurement to it.

Look at this image from page 18 of the MCP4725's [datasheet][1]:

[![I2C protocol description for MCP4725][2]][2]

It describes the operation is Fast Mode, which seems to be the correct mode for this. (Similar descriptions for the other modes can be found below that image). The first byte is done by the SoftWire library, but the following is your responsibility. The
next 2 bytes consist (in this order) of 2 bit's setting the Fast Mode, 2 bit's for the devices power down select (both zero for normal DAC operation) and then the 12 bits of the actual voltage value for the DAC.

At this point I will show another problem with your code. You read an analog voltage with the Arduinos ADC, which is a 10 bit number (of type `int`) and use it in

    Wire.write(aPin);

But the parameter for `Wire.write()` is defined as `uint8_t` (see [line92 in SoftWire.h of the Softwire library][3]), which means, that your `int` value get's casted and you loose all bits above 255 (the lower byte), because `uint8_t` just cannot store more.

**What you have to do:** You should put the I2C data bytes together in your code and then send them. This may look like this:

    byte byte1 = (aPin & 0x0F00) >> 8;
    byte byte2 = (aPin & 0xFF);

This code uses bitwise operators. The `&` will do an AND operation, the `>>` shifts the bits to the right by the amount after the operator. The `0x` denotes a value in hex representation (binary representation would be `0b`). So for the first byte we are doing an AND with the value `0x0F00`, which will give us a value with only the first 4 bits of the second byte of `aPin`. Then we shift the result 8 bits to the right, so that the remaining data is nicely aligned to the right of your byte. We don't need to include the mode bits and power down select bits here, since they are zero anyway. If you want to set them non-zero you could bitwise OR them (of course with the correct shift, so that the bits have the correct position in the resulting byte):

    byte mode_bits = 0b10;
    byte power_down_bits = 0b11;
    byte byte1 = (mode_bits << 6) | (power_down_bits << 4) | (aPin & 0x0F00) >> 8;

Then you can send these bytes out with I2C:

    Wire.beginTransmission(I2C_7BITADDR);
    Wire.write(byte1);
    Wire.write(byte2);
    Wire.endTransmission();

That should work, though note, that I have not tested this. I just read the datasheet, which is always a must read.

**What happened with your original code:** The datasheet states for the command "Write DAC Register" (which uses 4 bytes including the address byte) the following:

> The device ignores any partially received data  bytes  if  the  I2C
> communication with the Master ends before completing the 4th byte.

So it just drops any I2C messages, that are not complete. Though it is not stated clearly, we can be pretty sure, that the same happens also for the other operation modes. You were sending only 1 byte, so the MCP found the message incomplete and ignored it.

---

That said, there is a principle to work around the limit of only 2 devices on the same bus, which I also only learned recently about. You might not wanna go this way here, but it's a great idea and a valid solution to the problem with the limit.

Every MCP has 1 address pin A0, which set's 1 bit of the address, resulting in 2 possible addresses. On an I2C bus there must not be more than 1 device with the same address. But if that doubled address is never called, the bus doesn't have a problem.

You would connect the A0 pins of each MCP to one digital output pin of the Arduino each. By setting the state of these output pins you can change the address of the MCPs (requirement is, that the MCP actually checks the A0 pin during operation, but the datasheet seems to suggest this). Now you keep every A0 pin on one level, so that all MCPs have the same address. To communicate with one, you would change the state of it's A0 pin to change it's address. Now this MCP is the only MCP with this address (all other MCPs have the other address). You can now communicate with it. When you want to communicate with another MCP, you reset the first MCPs A0 pin and then change the next MCPs A0 pin.

That way you make sure, that on one of the two addresses, there will always be 1 MCP at maximum, while you never use the other address. You can use as many MCPs, as you have digital output pins to change their addresses.

  [1]: https://www.sparkfun.com/datasheets/BreakoutBoards/MCP4725.pdf
  [2]: https://i.stack.imgur.com/JGGO6.jpg
  [3]: https://github.com/felias-fogg/SoftI2CMaster/blob/6e8e7043392bed29cd2925d0a19fce5fc5d726c1/SoftWire.h#L92


message:
How can I use a transistor to "press" a button?

I have a heater remote that I want to press the buttons of with my Arduino. I am powering both the remote and Arduino from an external 5V source so both grounds are connected.

Currently I have tried using an NPN transistor(TIP122) and it does work but is not very reliable. It probably works 80% of the time but isn't good enough for my purpose. Sometimes nothing happens and sometimes the button is pressed twice for no reason.

These are my connections.[![enter image description here][1]][1]

I have the emitter connected to ground, collector connected to the button and the base connected to the Arduino with a 1k resistor. Are my connections OK?

I've also tried using a PNP transistor but pulling LOW instead of HIGH and LOW instead of HIGH.

The code is very simple, in the setup I have:

    pinMode(4, OUTPUT);
    digitalWrite(4, HIGH);
    delay(20);
    digitalWrite(4, LOW);

Therefore when I restart the Arduino it should press the button, right?

I also have IRLZ44N and IRF540N, would either of these work better?

  [1]: https://i.stack.imgur.com/Qjn6M.jpg

body:
A glance at the TIP22 datasheet shows that this is a Darlington pair transistor, which means that it has very high DC gain (good), but at the cost of a very high Vbe_ON (bad).  The datasheet shows that the Vbe_ON is 2.5V, which means that the voltage across the 1K is only 2.5V max, which limits the base current to around 2mA.  This is probably not enough for good saturation.  In addition, the Vce_SAT for this device is about 2.0V, which may or may not be enough to look like a good GND to the button circuit.

I think a MOSFET like the IRF540N, connected as shown [here][1] (substitute button circuit for motor) might be a better choice
YMMV

  [1]: https://components101.com/irf540n-pinout-equivalent-datasheet


body:
You really only need one wire and no resistors or mosfet.

I see many answers including expensive mosfets and relays to answer this question. There is a much simpler solution requiring no glue logic or interfacing circuitry. I recently had to install an off-the-shelf ultrasonic humidifier in an incubator/brooder. It is the cheap little home-use aromatherapy type diffuser. It had to be controlled by a relay to turn on and off. The catch is that the control circuit and firmware used in nearly all of these is the same, it can be turned on by a relay in the PID incubator controller but requires a single button press once power is supplied to start the ultrasonic humidifier and fan. three button presses turns the humidifier off and returns it to standby and turns off automatically when it runs out of water. using the arduino to control only the button to bring it out of standby would not lead to reliable operation. I searched for an answer but found none that I could make given I had few parts and was working on a remote farm. This is my solution.

The science behind this and how it works is that the microcontroller does not sense the press of a button, it detects a state change. You may familiarize yourself with this in the arduino tutorials for reading a button press.

Tie the arduino ground to ground in the circuit you want to control. find a 5v rail and power the arduino. no extra power required. There is usually a test pad that will be ground and 5v close to the button you want to control. if not, find the regulator for the microcontroller that you are trying to trigger by tracing the circuit and attach the power rails. I used Digital Pin 2 for the trigger signal. connect d2 to a point near the switch. Ensure there is a resistor of about 600-1000ohm in the circuit between the point and the microcontroller. This should be present on the circuit you are triggering already simply because this is how microcontrollers detect state changes without sinking or sourcing infinite current.

This code will trigger once and then go to sleep. The long delays are to allow for expected debounce code in the microcontroller and allow for boot time. put simply, it switches PD2 between high and low states in high impedance and low impedance states and basically all a switch does is switch between high impedance and low impedance states. This code should trigger pretty much any microcontroller regardless of the specific state required once and then go to sleep.

```
#include <avr/sleep.h>
void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  pinMode(PD2, INPUT_PULLUP);
  digitalWrite(PD2, HIGH);
  delay(2000);
  pinMode(PD2, OUTPUT);
  digitalWrite(PD2, HIGH);
  digitalWrite(13, HIGH);
  delay(300);
  digitalWrite(13, LOW);
  pinMode(PD2, INPUT_PULLUP);
  digitalWrite(PD2, HIGH);
  delay(300);
  pinMode(PD2, OUTPUT);
  digitalWrite(PD2, LOW);
  digitalWrite(13, HIGH);
  delay(300);
  digitalWrite(13, LOW);
  pinMode(PD2, INPUT_PULLUP);
  digitalWrite(PD2, LOW);
  delay(500);
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_cpu();
}

```


message:
Rate of serial communication (UART) of a sensor is faster than speed of processing of microcontroller

I have a Vector Nav VN100 IMU sensor that sends data serially UART. I have interfaced it with ATmega32. It receives data (ROLL angel) from the sensor and according to the ROLL angel, it controls a servo motor.

My question, if the sending rate is faster than processing speed of the ATmega32, then  some data from the sensor will be dropped. How to overcome this problem?

body:
When using an embedded processor's hardware implemented [UART][1], it is often the case that the rate at which the software processes the data is a fraction of the [Gross bit rate][2] some times referred to as the [Baud rate][2].  If the UART is configured to handle 8 bit [RS-232][3] where the Gross bit rate is 10000 bits per second, the processor only has to handle data at a faction of that rate.  Perhaps 1/10 given several bits of over head and space between characters.

Processor intervention can be further reduced if the hardware UART contains several bytes of buffering.  For every doubling of the number of hardware supported bytes of buffering, processor interventions events are cut in half.

Beyond this, there are embedded processors in which the UART supports [DMA or Direct Memory Accessing][4].  This is where the hardware UART will write the received data directly into the processor's memory with out need of processor intervention.  This feature is usually only found on feature rich embedded processors.

Study [this PDF][5] to understand the abilities and limitations of the ATmega32 processor.  Specifically the USART section starting on page 140.

  [1]: https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter
  [2]: https://en.wikipedia.org/wiki/Bit_rate#Gross_bit_rate
  [3]: https://en.wikipedia.org/wiki/RS-232
  [4]: https://en.wikipedia.org/wiki/Direct_memory_access
  [5]: http://ww1.microchip.com/downloads/en/devicedoc/doc2503.pdf


message:
Trouble with setting the PWM frequency for Arduino Due

I'm using Arduino Due and I set the analog read and write resolution to 12-bit for better resolution. Basically all I do is to vary PWM duty cycle by controlling analog DC input voltage from 0 to 3.3V. The simple code as it is now works fine as follows:
<!-- language-all: lang-cpp -->

    int pwmPin9 = 9;
    int analogPin0 = 0;
    int val = 0;

    void setup() {

      Serial.begin(9600);

      pinMode(pwmPin9, OUTPUT);  // sets the pin as output
      analogWriteResolution(12);
      analogReadResolution(12);

    }

    void loop() {

      val = analogRead(analogPin0);  // read the input pin
      Serial.println(val);
      analogWrite(pwmPin9, val);

    }

My problem is I need to set the frequency of the PWM output to 25kHz or at least something nearest above 25kHz.

I have been searching forums hours and couldn't find any solution. [Here][1] I came across a way but there is no library called variant.h in my folders. And that code if I include in my script doesn't change anything.
What could be a workaround for this?

(I used to achieve this via this site by using Arduino Uno but for Due couldn't find any working solution)

Edit: I found the file and made the following change in variant.h:

     * PWM
     */
    #define PWM_INTERFACE  PWM
    #define PWM_INTERFACE_ID ID_PWM
    #define PWM_FREQUENCY  20000
    #define PWM_MAX_DUTY_CYCLE 4095
    #define PWM_MIN_DUTY_CYCLE 0
    #define PWM_RESOLUTION  12

    /*
     * TC
     */
    #define TC_INTERFACE        TC0
    #define TC_INTERFACE_ID     ID_TC0
    #define TC_FREQUENCY        20000
    #define TC_MAX_DUTY_CYCLE   255
    #define TC_MIN_DUTY_CYCLE   0
    #define TC_RESOLUTION  8

But it only works for 20kHz. If I set to 25kHz or 30kHz I don't get any error but also don't get any output :((

  [1]: https://folk.uio.no/jeanra/Microelectronics/GettingTheBestOutOfPWMDue.html

body:
There are a few things to do. I've used this successfully in the past with older projects.

As a side note one can *very* easily change PWM settings on pins with the esp32, a single line of code being `ledcSetup(PWM_Channel_Number, Frequency, resolution)` without ever having to actually dive into modifying variant.h

To Quote [Kerry D. Wong][1]:

> If you take a look at the function PWMC_ConfigureClocks in pwmc.c, you will see that the highest PWM frequency can be accommodated as the function input is 42 MHz, this is because inside the function it calls FindClockConfiguration which in turn ensures that the frequency parameter passed in is less than the MCK frequency. Thus for integer dividers, the highest frequency we can pass in is 42 MHz (with divider 2).

> To achieve the highest output frequency, we can use a one bit PWM which essentially just outputs a square wave with a duty cycle of one. We can then set the prescaler to 2 to obtain an 84 MHz waveform.

    #include <Arduino.h>

    uint32_t pwmPin = 8;
    uint32_t maxDutyCount = 2;
    uint32_t clkAFreq = 42000000ul;
    uint32_t pwmFreq = 42000000ul;

    void setup() {
      pmc_enable_periph_clk(PWM_INTERFACE_ID);
      PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK);

      PIO_Configure(
        g_APinDescription[pwmPin].pPort,
        g_APinDescription[pwmPin].ulPinType,
        g_APinDescription[pwmPin].ulPin,
        g_APinDescription[pwmPin].ulPinConfiguration);

      uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel;
      PWMC_ConfigureChannel(PWM_INTERFACE, channel , pwmFreq, 0, 0);
      PWMC_SetPeriod(PWM_INTERFACE, channel, maxDutyCount);
      PWMC_EnableChannel(PWM_INTERFACE, channel);
      PWMC_SetDutyCycle(PWM_INTERFACE, channel, 1);

      pmc_mck_set_prescaler(2);
    }

    void loop()
    {

> Note that VARIANT_MCK is defined in /arduino-1.5.7/hardware/arduino/sam/variants/arduino_due_x/variant.h as 84000000. PWM_INTERFACE_ID and PWM_INTERFACE are defined in variant.h as ID_PWM and PWM which in turn are defined in /arduino-1.5.7/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h.

> So as the conclusion, the highest stable frequency we can generate using an Arduino Due is 84 MHz. The pictures below show the captured waveforms under different frequencies. For the 21 MHz waveform, pwmFreq is set to 21000000, no prescaler is used. For the 42 Mhz waveform, pwmFreq is set to 420000 with no prescaler. The 84 MHz waveform is generated with set to 42000000 and the prescaler set to 2.

Hope this helps.

  [1]: http://www.kerrywong.com/2014/09/21/on-arduino-due-pwm-frequency/


message:
Update `char* `

I have a class containing few `char*` variables:

    char* msgTopic     = "myHome/MSGS";
    char* groupTopic   = "myHome/All";
    char* errorTopic   = "myHome/Err";

but, I wish to have it defined outside the class and not hardcoded (update only `prefixTopic` outside the class,

    char* prefixTopic  = "myHome";
    char* msgTopic     = ""; // also tried-->  char* msgTopic = "AAAAAAAAAAA";
    char* groupTopic   = "";
    char* errorTopic   = "";

and then, down the code to have it defined as:

    sprintf(msgTopic  ,"%s/Messages",prefixTopic);
    sprintf(groupTopic,"%s/All",prefixTopic);
    sprintf(errorTopic,"%s/Errors",prefixTopic);

**BUT**

both ways ( when defining variables as `""`, or just filled it up with chars to allocate space) caused topics to be defined with errors ( mostly - one variable contained both topics ).

Appreciated any help
( I don't think context of class is relevant )

body:
First, you have to think about using dynamic or pre-allocated strings. Dynamic memory is not recommended for Arduino, so I will use pre-allocated strings.

In that case you need to think about the maximum length, I will take 32 for now:

    #include <stdio.h>

    class YourClass
    {
      static const int MaxTopicLength = 32;

      char _msgTopic[MaxTopicLength];
      char _groupTopic[MaxTopicLength];
      char _errorTopic[MaxTopicLength];

      void FillStrings(const char* prefixTopic);
    };

Than create in your class a function to fill the strings (untested):

    void YourClass::FillStrings(const char* prefixTopic)
    {
      snprintf(_msgTopic  , MaxTopicLength, "%s/Messages", prefixTopic);
      snprintf(_groupTopic, MaxTopicLength, "%s/All"     , prefixTopic);
      snprintf(_errorTopic, MaxTopicLength, "%s/Errors"  , prefixTopic);
    }


message:
Timer Countdown to control relay (multiple functions in void loop)

[![project][1]][1]
I'm trying to build this project with a simple code.
Object is to hit up button to increment minutes or down to decrement minutes then hit start to start countdown,
while its counting relay will turn On light till counting is done will turn light off and if I hit end button while counting it will end counting and turn off relay.

Here is my try I would appreciate if you could support me.
i can not move to countDown() function in the loop if i press start
I need help to figure out a good technique of declaring functions in void loop in arduino
<!-- language-all: lang-cpp -->

    #include <LiquidCrystal.h>

    LiquidCrystal lcd(1,2,4,5,6,7);

    #define numberOfSeconds(num) ((num/1000) % 60 )
    #define numberOfMinutes(num) (((num/1000) / 60) % 60)

    //unsigned long timeLimit = 3600000; // 1000 ms in 1sec, 60secs in 1min, 60mins in 1hr. so , 1000x60x60 = 3600000ms = 1hr

    const int upBtn = 8;
    const int downBtn = 9;
    const int startBtn = 10;
    const int endBtn = 11;

    int btnPushCounter = 0;
    int minutes;
    int seconds;
    unsigned long minutesGiven;
    unsigned long timeLimit;
    unsigned long timeRemaining;

    int upBtnState = 0;
    int lastUpBtnState = 0;

    int downBtnState = 0;
    int lastDownBtnState = 0;

    int startBtnState = 0;
    int lastStartBtnState = 0;

    int endBtnState = 0;
    int lastEndBtnState = 0;

    bool bPress = false;

    void setup() {

     lcd.begin(16,2);
     pinMode(upBtn, INPUT_PULLUP);
     pinMode(downBtn, INPUT_PULLUP);
     pinMode(startBtn, INPUT_PULLUP);
     pinMode(endBtn, INPUT_PULLUP);

     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print("Minutes : ");
     lcd.print(btnPushCounter);
    }
    void loop() {

        checkUp();
        checkDown();
    //    countDown();
        if(bPress){
          bPress = false;
          displayNumber();
        }
    }

    void displayNumber(){
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Minutes : ");
        lcd.print(btnPushCounter);
    }

    void checkUp(){
      upBtnState = digitalRead(upBtn);
      // compare the buttonState to its previous state
      if (upBtnState != lastUpBtnState) {
        // if the state has changed, increment the counter
        if (upBtnState == HIGH) {
            bPress = true;
          btnPushCounter++;
        }
        delay(50);
      }
      // save the current state as the last state, for next time through the loop
      lastUpBtnState = upBtnState;
    }

    void checkDown(){
      downBtnState = digitalRead(downBtn);

      // compare the buttonState to its previous state
      if (downBtnState != lastDownBtnState && btnPushCounter != 0 ) {
        // if the state has changed, increment the counter
        if (downBtnState == HIGH) {
            bPress = true;
          btnPushCounter--;
        }
        // Delay a little bit to avoid bouncing
        delay(50);
      }
      // save the current state as the last state, for next time through the loop
      lastDownBtnState = downBtnState;
    }

    void checkStart(){
      startBtnState = digitalRead(startBtn);
      if(startBtnState != lastStartBtnState){
        if(startBtnState == HIGH){
          bPress = true;
    //      lcd.
        }
      }
    }

    void countDown() {
    //  unsigned long timeLimit = 3600000;
      minutesGiven = btnPushCounter;
      timeLimit = minutesGiven * 1000 * 60;
      timeRemaining = timeLimit - millis();
      while(timeRemaining > 0){
        seconds = numberOfSeconds(timeRemaining);
        minutes = numberOfMinutes(timeRemaining);
        lcd.setCursor(2,7);
        lcd.print(minutes);
        lcd.print(" ");
        lcd.print(seconds);
        delay(50);
        timeRemaining = timeLimit - millis();
      }
    }

  [1]: https://i.stack.imgur.com/pssjw.jpg

body:
I think what you're looking for is to declare your functions near the top of your file, usually before the first function you write, `setup()`, in this case. So add this just above your `setup()` function:

    // Forward function declarations
    void displayNumber(void);
    void checkUp(void);
    void checkDown(void);
    void checkStart(void);
    void countDown(void);

C compilers (and thus, C++ because it was derived from C) read the source code only once through, so any function must become known to the compiler ahead of where it is first called. This would require you to place all low-level functions first, then all functions that call those, then the functions that call those, ..., etc. And there are some cases that even this arrangement won't solve, e.g., functions that call each other (oww, my brain hurts!!). So function declarations are used to avoid this inconvenience.

Declaring a function just means informing the compiler of its name, the parameter types, and the return type -- the actual function code isn't required at this point.


message:
Arduino digital pin status not transmitting via NRF24L01 where as analog pin status is getting transmitted ,Why?

I am currently working with a project using NRF24L01 which I integrated with my Joystick so that I can make it wireless.While transmitting the information in my Joystick to the receiver only analog pin status is getting transmitted where as digital pin status is not getting transmitted.

    Transmitter Code:

    #include <nRF24L01.h>
    #include <printf.h>
    #include <RF24.h>
    #include <RF24_config.h>
    #include <SPI.h>
    #include <Wire.h>

    //Define the digital inputs
    #define tGL1 7
    #define tGL2 6
    #define b1 5
    #define b2 4
    #define b3 3
    #define b4 2

    const int MPU = 0x68; // MPU6050 I2C address
    float AccX, AccY, AccZ;
    float GyroX, GyroY, GyroZ;
    float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
    float angleX, angleY;
    float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
    float elapsedTime, currentTime, previousTime;
    int c = 0;

    RF24 radio(9,10);
    const byte address[6]="00001";

    struct Data_Package {
      byte j1PotX;
      byte j1PotY;
      byte j2PotX;
      byte j2PotY;
      byte button1;
      byte button2;
      byte button3;
      byte button4;
      byte tSwitch1;
      byte tSwitch2;
      byte pot1;
      byte pot2;
    };

    Data_Package data;

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

      radio.begin();
      radio.openWritingPipe(address);
      radio.setAutoAck(false);
      radio.setDataRate(RF24_250KBPS);
      radio.setPALevel(RF24_PA_LOW);

      pinMode(tGL1, INPUT_PULLUP);
      pinMode(tGL2, INPUT_PULLUP);
      pinMode(b1, INPUT_PULLUP);
      pinMode(b2, INPUT_PULLUP);
      pinMode(b3, INPUT_PULLUP);
      pinMode(b4, INPUT_PULLUP);

       data.j1PotX = 127; // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that's one BYTE value
       data.j1PotY = 127;
       data.j2PotX = 127;
        data.j2PotY = 127;
    //  data.j1Button = 1;
    //  data.j2Button = 1;
      data.pot1 = 1;
      data.pot2 = 1;
      data.tSwitch1 = 1;
      data.tSwitch2 = 1;
      data.button1 = 1;
      data.button2 = 1;
      data.button3 = 1;
      data.button4 = 1;

    }

    void loop() {
      // put your main code here, to run repeatedly:
      data.j1PotX = map(analogRead(A2), 0, 1023, 0, 255); // Convert the analog read value from 0 to 1023 into a BYTE value from 0 to 255
      data.j1PotY = map(analogRead(A1), 0, 1023, 0, 255);
      data.j2PotX = map(analogRead(A3), 0, 1023, 0, 255);
      data.j2PotY = map(analogRead(A0), 0, 1023, 0, 255);
      data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
      data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);

      data.tSwitch2 = digitalRead(tGL2);

      data.button1 = digitalRead(b1);
      data.button2 = digitalRead(b2);
      data.button3 = digitalRead(b3);
      data.button4 = digitalRead(b4);

      if (digitalRead(tGL1) == 0) {
        read_IMU();    // Use MPU6050 instead of Joystick 1 for controling left, right, forward and backward movements
      }

      radio.write(&data, sizeof(Data_Package));
    }

This is the Reciever Code

    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
    const byte address[6] = "00001";
    unsigned long lastReceiveTime = 0;
    unsigned long currentTime = 0;
    // Max size of this struct is 32 bytes - NRF24L01 buffer limit
    struct Data_Package {
      byte j1PotX;
      byte j1PotY;
      byte j2PotX;
      byte j2PotY;
      byte pot1;
      byte pot2;
      byte tSwitch1;
      byte tSwitch2;
      byte button1;
      byte button2;
      byte button3;
      byte button4;
    };
    Data_Package data; //Create a variable with the above structure
    void setup() {
      Serial.begin(9600);
      radio.begin();
      radio.openReadingPipe(0, address);
      radio.setAutoAck(false);
      radio.setDataRate(RF24_250KBPS);
      radio.setPALevel(RF24_PA_LOW);
      radio.startListening(); //  Set the module as receiver
      resetData();
    }
    void loop() {
      // Check whether there is data to be received
      if (radio.available()) {
        radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
        lastReceiveTime = millis(); // At this moment we have received the data
      }
      // Check whether we keep receving data, or we have a connection between the two modules
      currentTime = millis();
      if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
        resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone has a throttle up and we lose connection, it can keep flying unless we reset the values
      }
      // Print the data in the Serial Monitor
      Serial.print("j1PotX: ");
      Serial.print(data.j1PotX);
      Serial.print("; j1PotY: ");
      Serial.print(data.j1PotY);
      Serial.print("; button1: ");
      Serial.print(data.button1);
      Serial.print("; j2PotX: ");
      Serial.println(data.j2PotX);
    }

When I print the status of the buttons and Joystick in my transmitter(Joystick) I get the correct status of my push button when I press but the status of my push button remain unchanged in the Serial monitor of my Receiver despite there is change other values (I mean the analog value is transmitting correctly)

This the screenshot of my both serial Monitor
[![COM7 is my Transmitter but COM6 is Receiver but change in state of button1 is COM7 is not produced in COM6][1]][1]

  [1]: https://i.stack.imgur.com/uvOGZ.png

body:
As Mikael Patel mentions in the comments: your structures do not match between the transmitter and receiver.

    Transmitter               Receiver
    =====================     =====================
    struct Data_Package {     struct Data_Package {
          byte j1PotX;    ->      byte j1PotX;
          byte j1PotY;    ->      byte j1PotY;
          byte j2PotX;    ->      byte j2PotX;
          byte j2PotY;    ->      byte j2PotY;
          byte button1;   ->      byte pot1;
          byte button2;   ->      byte pot2;
          byte button3;   ->      byte tSwitch1;
          byte button4;   ->      byte tSwitch2;
          byte tSwitch1;  ->      byte button1;
          byte tSwitch2;  ->      byte button2;
          byte pot1;      ->      byte button3;
          byte pot2;      ->      byte button4;
    };                        };

With structures, what matters is *not* what each field is called. What matters is the position of the fields in the list.  When you compile your code all the names are lost. All that is left is where in the list each entry is.

The best way of avoiding this problem is to have a single header file (make it a library so it's easy to share) that contains the packet structure. Then if you ever make any changes to the packet all the sketches that use it see that change the next time you compile them.


message:
RTC timer set point problem

This is the timer part of my code:

    int onHourONE = 11;
    int onMinuteONE = 00;
    int offHourONE = 23;
    int offMinuteONE = 00;
    byte PWMstatus = 0;

    void setup{}

    void loop{
        if ((now.hour() >= onHourONE) && (now.minute() >= onMinuteONE)) {
          PWMstatus = 1;
        }
        if ((now.hour() >= offHourONE) && (now.minute() >= offMinuteONE)) {
          PWMstatus = 2;
        }
        if (PWMstatus == 1) {
          // do this
        }
        if (PWMstatus == 2) {
          // do that
    }

It's working just fine but the problem is if i set the `offhourONE` less than `onhourONE` it will keep the LED OFF.

for example the time is now 14:00

`onhourONE` and `offminuteONE` is also set on 14:00

`offhourONE` and `offminuteONE` is set on 13:00

So in this case it should keep the LED ON until tomorrow 13:00 **but** it stays OFF obviously because of this statement:

    if ((now.hour() >= offHourONE) && (now.minute() >= offMinuteONE)) {}

I can change that to this:

    if ((now.hour() == offHourONE) && (now.minute() == offMinuteONE)) {}

But then it will only turn OFF the LED at that specific time, in this case if i restart the Arduino like 1 minute after it turned OFF it will turn on again while it should stay off until it reaches the set point of turn ON.

*I know it sounds simple but seems confusing to me, any guidance appreciated...*

body:
If it overly complicated to use a combination of seconds, minutes and hours for comparisons. For this you can use the time in seconds, as you get it with `now.secondstime()` or `now.unixtime()`. If you don't want to look at the seconds (so only values multiple to 60), you can do an integer division to get the minutes `now.secondstime()/60`.

To calculate the needed limit values from the combination of hour and minutes, just multiply according to the unit. For seconds `(hour*60+minutes)*60`. For minutes `hour*60+minutes`.


body:
You need to add more logic to your program.

As mentioned in another answer you really want to be working with just the highest resolution time interval that matters to you - that is minutes in your case.  Convert your hour and minutes of the day into the number of minutes since midnight:

    onTime = onHourONE * 60 + onMinuteONE;
    offTime = offHourONE * 60 + offHourONE;

And convert the current time to minutes since midnight:

    timeNow = now.hour() * 60 + now.minute();

Now comes the tricky bit, but since you are now just working with single numbers it's far easier.  You now need to work out *what* you are doing.

You have a couple of scenarios:

1. onTime < offTime - eg: 12:00 to 17:00
2. onTime > offTime - eg: 21:00 to 03:00

You need to make your decision in a different way depending on which scenario you are in - and comparing a single number with a single number is so much easier than messing with hours and minutes.

So, you can do something like:

    if (onTime < offTime) {
        if ((timeNow >= onTime) && (timeNow < offTime)) {
          // On!
        } else {
          // Off!
        }
    } else {
        if ((timeNow >= onTime) || (timeNow < offTime)) {
          // On!
        } else {
          // Off!
        }
    }

In English:

* If the start time is before the end time:
  * If the time is both greater than the start time and less than the end time, then it's on.
  * Otherwise it's off.
* Otherwise, of the start time is after the end time:
  * If the time is greater than the start time, *or* it's less than the end time, then it's on.
  * Otherwise it's off.


message:
Serial.println() cuts off characters

I want to print a string together with number. My code is

    Serial.println("Test " + index++);
(In `setup()` I initialized variable `index` to 0.) In Java it would output

    Test 0
    Test 1
    Test 2
    Test 3
    ...
But I get this output instead:

    Test
    est
    st
    t

Can anybody explain it to me please?

body:
`Serial.println()` prints the value of one expression. The expression you passed it was `("Test " + index++).

In C/C++ a character literal such as "Test " evaluates to the memory address its first character. Adding 1 to that address gives the address of the next (or 2nd) character. Adding 2 to it gives the address of the 3rd character, and so on.

To get what you were expecting, the value of the literal, AND the value of the index, you would write:

    Serial.print("Test ");
    Serial.println(index++);

If you had created a String variable with the value "Test ", then the String expression, `("Test " + index++)` would have been evaluated differently: The "+" operator would have concatenated the String "Text ", with the String equivalent of the current value of "index"; but that isn't the way a character literal is treated. There is a C++ String library among the Arduino libraries but it's use is not recommended because Strings get reallocated and copied when they get concatenated, resulting in excessive memory use, and the Arduino has very little memory.


body:
JRobert explains very well why it does not work.

Instead of the Serial.print you also can use the sprintf function in case you need a more complicated string to build, or in case you want to mix two different types in one line:

    char str[100];
    int index = 0;
    sprintf(str, "Test %d", index++);
    Serial.println(str);

Make sure the buffer (100) is big enough to store the full string including the end symbol ('\0').

For safety you also can use:

    snprintf(str, 100, "Test %d", index++);

This will make sure max. 100 characters are filled in (and the remainder is clipped).