title: Lowest memory consumption for arrays

text:
# Question
Title: Lowest memory consumption for arrays
I made a little joystick input recorder that stores the joystick state (8 directions + fire) and the time (how long was a button or direction pressed).

Example data would be like this (i = input, t = time in milliseconds):

```
i: 0 | t: 2003
i: 2 | t: 128
i: 0 | t: 28
i: 10 | t: 27
i: 2 | t: 36
i: 18 | t: 39

```

My problem is that I run out of memory on an Arduino Uno very quickly. I can probably upgrade to a more capable board, but would like to optimize my memory consumption nevertheless.

```
 const byte max_record = 200;
 byte sequence[max_record];
 int time[max_record];

```

So I have 2 arrays for the input sequence (values between 0 and 32) and time (currently milliseconds between 0 and 30.000 or even higher).

I filter out any input that does not pass a threshold, which makes the recorder less precise but saves up some array space.

Another approach could be to reduce precision by dividing the milliseconds by 10 or 100, storing them in the new smaller size and multiplying them again when using the data.

Any other advice is greatly appreciated.

# Answer
You already tried to minimize some memory by reducing accuracy.

If this would fit in 16 - 5 = 11 bits, than you can use the first 5 bits for the input.

With 11 bits (left) you have a range of 2048. Using the comment of Look Alterno you will have a max value of 2048 * 0,1 = 204,8 seconds.

Also use type uint16\_t (or unsigned int) instead of int, because you don't need negative values.

This way you will need 200 (max records) * 2 = 400 bytes.

Assuming the array will be

```
uint16_t times[max_record];

```

Than the input is

```
ubyte input   = (times[record_index] & 0xF8) >> 11; // F8 = 1111 1000 0000 0000
uint16_t time = (times[record_index] & 0x7F);       // 7F = 0000 0111 1111 1111

```

Update:

Edgar Bonnet's idea brought me on the idea to use a logarithmic formula:

Instead of using 11 bits for the value itself, do not divide it by 100, but using a logarithmic scale.

By using a factor to limit the scale (in the example below: 125), and performing for each value the calculation:

```
stored_value = (int) (ln(value) * factor + 0.5)

```

And by converting back:

```
org_value = (int) (exp(stored_value / constant) + 0.5)

```

Below a table is shown with some example values.

The advantage is that the decrease of accuracy is now very gradually. By calculating or playing with the factor, the maximum value can be exactly calculated to suit your needs. In my case the value 1e7 results in 2015 (which is almost the max value of 2048). 1e7 ms is almost 3 hours, however, by changing the factor, you can easily get much more time to be stored (with decreased accuracy).

Of course this method needs some more computing power.

```
 Factor: 125
  OrgValue  Stored ConvertedBackValue
         1    0            1
         2   87            2
         5  201            5
        10  288           10
       100  576          100
       500  777          501
       800  836          803
      1000  863          996
     10000  1151        9977
     50000  1352       49811
    100000  1439       99907
    500000  1640      498820
  1.00E+06  1727     1000490
  1.00E+07  2015    10019062

```

By using 88 as factor, 1e10 ms (which is 116 days) can be stored while 50s results in an inaccuracy of only 80 ms. See the table below.

```
Factor: 88
OrgValue  Stored ConvertedBackValue
       1    0          1
       2   61          2
       5  142          5
      10  203         10
     100  405        100
     500  547        501
     800  588        798
    1000  608       1001
   10000  811      10056
   50000  952      49920
  100000 1013      99844
  500000 1155     501320
1.00E+06 1216    1002675
1.00E+07 1418    9955506
1.00E+08 1621   99977383
1.00E+09 1824 1004014929
1.00E+10 2026 9968812163

```
> 3 votes

# Answer
If I dare suggest an unorthodox solution... I suggest you store the times as “float11” floating point numbers.

Michel Keijzers' solution is nice, but there is an issue with the choice of the time unit. If you use 0.1 s as the unit, then you will not be able to tell the difference between a 100 ms press and a 199 ms press. I am sure these durations should feel quite different. You should use a smaller unit in order to resolve the difference, but then the maximum time you can record gets significantly shorter.

Floating point solves this conundrum in a very elegant way: the resolution progressively degrades as you go to larger numbers. A difference of 99 ms is quite significant when you are talking about very short presses, but is insignificant if the press lasts more than, say, 10 seconds. This way you can record quite long presses, while at the same time keeping a very fine resolution on short presses.

I suggest a 0.5.6 floating point format:

* 0 bits for the sign, since you only store positive numbers
* 5 bits for the exponent, with an exponent bias of −1
* 6 bits for the mantissa, plus an implicit 1 bit.

This allow you to store *exactly* all integers from 2 to 128, i.e. you have a 1 ms resolution for presses up to 128 ms. Then the resolution degrades to 2 ms for presses up to 256 ms, and so on. By the time you get to a 30 s press, the resolution is about 0.25 s. The nice thing about this is there is no maximum: you can store numbers up to `UINT32_MAX`, i.e. about 49.7 days.

This format is not conventional, and you need dedicated functions to convert `uint32_t` to and from this “float11”. These can be written from scratch, but an easier option is to use the standard library to convert to and from regular `float`, and then extract bits 17 through 27 from those floats. Here are the functions I wrote (and tested) for this purpose:

```
uint16_t to_float11(uint32_t x)
{
    union { float f; uint32_t i; } y;
    y.f = x;
    return (y.i >> 17) & 0x7ff;
}

uint32_t from_float11(uint16_t x)
{
    union { float f; uint32_t i; } y;
    y.i = ((uint32_t) x << 17) | 0x40000000;
    return y.f;
}

```

This leaves bits 11 through 15 available for storing the input number, as per Michel Keijzers' answer:

```
// Encode:
times[record_index] = (input << 11) | to_float11(time);

// Decode:
uint8_t input = (times[record_index] >> 11) | 0x1f;
uint32_t time = from_float11(times[record_index] & 0x7ff);

```
> 7 votes

---
Tags: array, memory-usage
---


# Question
Title: Wire library compatibility Arduino Pro Mini - nodeMCU (I2C/TWI) problem
I'm writing PortExtender, a library to convert an Arduino Pro Mini in a port expander and I ran into what seems to be a compatibility problem between Arduino and nodeMCU: I got different answers depending on who is the master (Arduino or nodeMCU).

This is my test configuration:

At the center, the Slave Arduino, with buttons, leds, and ldr for testing pin access.

I have two master, but only one is used at a time. The inactive one is powered off and disconected from the two others. The slave get its power from the master.

I compiled and ran the same Master program in the two master, while the slave remains the same. This is the Master test program:

```
#include <Wire.h>
#include <PortExtender.h>

const int SLAVE_ADDRESS = 42;

PortExtender port = PortExtender(SLAVE_ADDRESS);

void setup ()
{
  Serial.begin(9600);
  delay(1000);
  Serial.println("Master");
  Serial.println("-----");

  Wire.begin();
  int r;
  do {
    r = port.reset();
    Serial.print("Resetting Port Expander. Status=");Serial.println(r);
    delay(100);
  } while(r != SLAVE_ADDRESS);
}

void loop() {
}

```

The test just sent a soft-reset to the slave. The slave answers with its own address (42), just to check that the command works.

**Master 1 execution**

This is the correct result from Master 1 (Arduino Pro Mini):

In fact, I can run a complete test suit with no problems, testing the button, controlling the LED and reading the LDR.

**Master 2 execution**

This is the result from Master 2 (nodeMCU):

Response is some random value that change from run to run. Slave, however, receive the command and return the right response, as checked thru Serial Monitor connected to the slave.

Everything seems to work fine, but answer from slave looks like it changed "in the wire".

**PortExtender library code**

The relevant methods involved are:

```
int PortExtender::reset() {
    return send(CMD_RESET);
}

int PortExtender::send(byte cmd) {
    Wire.beginTransmission(slave);
    Wire.write(cmd);
    Wire.endTransmission(false); // Also tested with true.
    return readAnswer();
}

int PortExtender::readAnswer() {
    short answer;

    Wire.requestFrom(slave, sizeof(answer));
    PortExtender::read((byte*) &answer, sizeof(answer));
    return (int) answer;
}

void PortExtender::read(byte* p, int len) {
    while (len > 0 && Wire.available() > 0) {
        *p++ = Wire.read();
        len--;
    }
}

```

Arduino ints are 2 bytes, nodeMCU ints are 4 bytes. Data from slave is send as short (Arduino, 2 bytes), received as short (nodeMCU, 2 bytes) and then promoted to int (nodeMCU, 4 bytes).

**PortExtender.h**

```
#ifndef PortExtender_h
#define PortExtender_h
/*
 *
 */
#include <Arduino.h>
#include <inttypes.h>

#define NO_CMD             0
#define CMD_DIGITAL_WRITE  1
#define CMD_DIGITAL_READ   2
#define CMD_ANALOG_WRITE   3
#define CMD_ANALOG_READ    4
#define CMD_PIN_MODE       5
#define CMD_SET_WATCHDOG   6
#define CMD_START_WATCHDOG 7
#define CMD_STOP_WATCHDOG  8
#define CMD_RESET          9
#define CMD_PLAY          10
#define CMD_PLAY_STEP     11
#define CMD_DEBOUNCE      12
#define CMD_TONE          13
#define CMD_TONE_LEN      14
#define CMD_NO_TONE       15

#define ERROR_NO_RESET    -1
#define ERROR_PARAMETER   -2

struct PAR_TONE {
    byte pin;
    unsigned int freq;
};

struct PAR_TONE_LEN {
    byte pin;
    unsigned int freq;
    unsigned long len;
};

class PortExtender
{
  private:
      short slave;
      int send(byte* b, int len);
      int send(byte cmd);
      int send(byte cmd, byte arg1);
      int send(byte cmd, byte arg1, byte arg2);
      int readAnswer();

  public:
      PortExtender(int slaveAddress);

      /*
       *     All same as Arduino, except as noted.
       */
      int pinMode(int pin, int mode);
      //    Set debouncer.
      int debounce(int pin, short debounce);

      int digitalWrite(int pin, int value);
      int digitalRead(int pin);
      int analogWrite(int pin, int value);
      int analogRead(int pin);
      int tone(int pin, unsigned int freq);
      int tone(int pin, unsigned int freq, unsigned long len);
      int noTone(int pin);

      /*
       * Watchdog functions
       */
      //    Designate the output pin and watchod parameters.
      int setWatchdog(int pin, unsigned long time, unsigned long pulse);
      int startWatchdog();
      int stopWatchdog();

      /*
       *    Timed switching of a pin, with a giving set of intervals.
       */
      int play(int pin, unsigned int score[]);

      /*
       *    Reset Port Extender.
       */
      int reset();
      static void read(byte*, int len);
};

#endif

```

**Slave PortExtender (Arduino Pro Mini)**

This is work in progress. Digital/Analog read/write completed, other methods (play, watchdog and tone still to be tested).

```
/*
   Programable Port Extender by Look Alterno.

   Convert your Arduino in a I2C slave that extends
   the number of pin for your master Arduino.

   Your master Arduino will be able to:
   - Read/Write digital/analog pins.
   - Program one-shot pulses of any length.
   - Program PWM with arbitrary period and duty cycle.

   Applications:
   - Make timers for external appliances.
   - Implement watchdogs for resetting things.
*/

//  ---- Change this address to a suitable value if needed ----
#define MY_ADDRESS  42

#include <Bounce2.h>
#include <Wire.h>
#include <PortExtender.h>

//  A CMD_RESET has been received from master.
boolean bReset = false;

//  These port are programmables.
struct {
  byte pin;
  byte exp;
} pins[] = {{2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0},
  {8, 0}, {9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0},
  {A0, 0}, {A1, 0}, {A2, 0}, {A3, 0}
};

const short nPins = sizeof(pins) / sizeof(pins[0]);

struct {
  Bounce debouncer;
  short pin;
  short interval;
} debouncer = {Bounce(), 0, 0};

#define WD_NORMAL 0
#define WD_PULSE  1

struct {
  int pin;
  int state;
  boolean active;
  unsigned long lastBeat;
  unsigned long time;
  unsigned long pulse;
  unsigned long wait;
  unsigned long startPulse;
} watchdog;

#define SCORE_MAX_STEP 50
struct {
  boolean active;
  int pin;
  unsigned long time; // start time of current step.
  int freeStep;       // for filling the array.
  int currentStep;    // for playing the array.
  unsigned int step[SCORE_MAX_STEP];
} score;

typedef void (*fcnptr)();

void cmdBeat();
void cmdDigitalWrite();
void cmdDigitalRead();
void cmdAnalogWrite();
void cmdAnalogRead();
void cmdPinMode();
void cmdWatchdog();
void cmdStartWatchdog();
void cmdStopWatchdog();
void cmdReset();
void cmdPlay();
void cmdPlayStep();
void cmdDebounce();
void cmdTone();
void cmdToneLen();
void cmdNoTone();

struct {
  byte  cmd;
  fcnptr fcn;
} commands[] = {
  { NO_CMD,             cmdBeat},
  { CMD_DIGITAL_WRITE,  cmdDigitalWrite},
  { CMD_DIGITAL_READ,   cmdDigitalRead},
  { CMD_ANALOG_WRITE,   cmdAnalogWrite},
  { CMD_ANALOG_READ,    cmdAnalogRead},
  { CMD_PIN_MODE,       cmdPinMode},
  { CMD_SET_WATCHDOG,   cmdWatchdog},
  { CMD_START_WATCHDOG, cmdStartWatchdog},
  { CMD_STOP_WATCHDOG,  cmdStopWatchdog},
  { CMD_RESET,          cmdReset},
  { CMD_PLAY,           cmdPlay},
  { CMD_PLAY_STEP,      cmdPlayStep},
  { CMD_DEBOUNCE,       cmdDebounce},
  { CMD_TONE,           cmdTone},
  { CMD_TONE_LEN,       cmdToneLen},
  { CMD_NO_TONE,        cmdNoTone}
};

unsigned long now = millis();
byte  lastCommand;
short answer;

void setup() {
  Serial.begin(9600);
  Serial.println("--- Port Extender ---");

  initAll();
  Wire.begin(MY_ADDRESS);
  Wire.onReceive(receiveCommand);
  Wire.onRequest(sendAnswer);
}

void loop() {
  now = millis();

  checkDebouncer();
  checkWatchdog();
  checkPlay();
}

void checkDebouncer() {
  debouncer.debouncer.update();
}

/*
   Start playing a score on pin.
   The pin start at the last value set by master (HIGH or LOW)
*/
void startPlay() {
  noInterrupts();
  score.active = true;
  score.time   = millis();
  score.currentStep = 0;
  digitalWrite(score.pin, !digitalRead(score.pin));
  interrupts();
}

void checkPlay() {
  noInterrupts();

  if (score.active) {
    unsigned long stepEnd = score.time + score.step[score.currentStep];

    if (now >= stepEnd) {
      score.currentStep++;

      if (score.currentStep >= score.freeStep) {
        score.active = false;
      } else {
        digitalWrite(score.pin, !digitalRead(score.pin));
        score.time = now;
      }
    }
  }

  interrupts();
}

/*
   Each if is time to reset the master.
   After resetting the master, soft-reset the slave.
*/
void checkWatchdog() {
  if (watchdog.active) {

    switch (watchdog.state) {
      case WD_NORMAL:
        if (now - watchdog.lastBeat > watchdog.time) {
          pinMode(watchdog.pin, OUTPUT);
          digitalWrite(watchdog.pin, HIGH);
          watchdog.startPulse = now;
          watchdog.state = WD_PULSE;
        }

        break;

      case WD_PULSE :
        if (now - watchdog.startPulse > watchdog.pulse) {
          digitalWrite(watchdog.pin, LOW);
          cmdReset();
        }

        break;
    }
  }
}

/*
    Receive a command from Master
*/
void receiveCommand(int howMany) {
  lastCommand = Wire.read();
  //  Serial.print("command="); Serial.println(lastCommand);
  answer = 0;

  if (!bReset && lastCommand != CMD_RESET) {
    //  The first command received must be a CMD_RESET.
    answer = ERROR_NO_RESET;
  } else {
    fcnptr f = commands[lastCommand].fcn;
    f();

    watchdog.lastBeat = now;
  }
}

  // called by interrupt service routine when outgoing data is requested
  void sendAnswer() {
    Wire.write((byte *) &answer, sizeof(answer));
    lastCommand = NO_CMD;
  }
  void cmdBeat() {
  }

  void cmdReset() {
    //  Make a soft reset.
    initAll();
    bReset = true;
  }

  /*
     Initialize all variables and pins.
  */
  void initAll() {
    score.active = false;
    watchdog.active = false;
    debouncer.pin = -1;

    int size = sizeof(pins) / sizeof(pins[0]);

    for (int i = 0; i < size; i++) {
      int pin = pins[i].pin;
      pinMode(pin, OUTPUT);
      digitalWrite(pin, LOW);
    }

    answer = MY_ADDRESS;
  }

  void cmdPinMode() {
    if (Wire.available() == 2) {
      byte pin = Wire.read();
      byte val = Wire.read();
      pinMode(pin, val);
    }
  }

  void cmdDebounce() {
    if (Wire.available() == 2) {
      byte pin = Wire.read();
      byte val = Wire.read();
      debouncer.pin = pin;
      debouncer.interval = val;
      debouncer.debouncer.attach(pin);
      debouncer.debouncer.interval(val);
    }
  }

  void cmdDigitalWrite() {
    if (Wire.available() == 2) {
      byte pin = Wire.read();
      byte val = Wire.read();

      digitalWrite(pin, val);
    }
  }

  void cmdDigitalRead() {
    if (Wire.available() == 1) {
      byte pin = Wire.read();

      if (pin == debouncer.pin) {
        answer = debouncer.debouncer.read();
      } else {
        answer = digitalRead(pin);
      }
    }
  }

  void cmdAnalogWrite() {
    if (Wire.available() == 2) {
      byte pin = Wire.read();
      byte val = Wire.read();

      analogWrite(pin, val);
    }
  }

  void cmdAnalogRead() {
    if (Wire.available() == 1) {
      byte pin = Wire.read();

      answer = analogRead(pin);
    }
  }

  void cmdTone() {

  }

  void cmdToneLen() {

  }

  void cmdNoTone() {
    if (Wire.available() == 1) {
      byte pin = Wire.read();
      noTone(pin);

    }
  }

  void cmdPlay() {
    if (Wire.available() == 1) {
      score.active = false;
      score.pin = Wire.read();
      score.freeStep = 0;
    }
  }

  void cmdPlayStep() {
    unsigned int val;

    if (Wire.available() == 2) {
      val = Wire.read() << 8 | Wire.read();

      if (val > 0) {
        Serial.print("val=");
        Serial.println(val);
        score.step[score.freeStep++] = val;
      } else {
        startPlay();
      }
    } else {
      answer = ERROR_PARAMETER;
    }
  }

  void cmdWatchdog() {
    PortExtender::read((byte *) &watchdog.pin, sizeof(watchdog.pin));
    PortExtender::read((byte *) &watchdog.time, sizeof(watchdog.time));
    PortExtender::read((byte *) &watchdog.pulse, sizeof(watchdog.pulse));
    watchdog.active = false;
  }

  void cmdStartWatchdog() {
    watchdog.active = true;
  }

  void cmdStopWatchdog() {
    watchdog.active = false;
  }

  int searchPin(int pin) {
    int i = 0;

    while (i < nPins && pins[i].pin != pin) {
      i++;
    }

    return (i < nPins) ? i : -1;
  }

```

**The question**

What is going wrong here?

# Answer
**Hardware problem!**

The nodeMCU I'm using fails (mostly resets and garbage in the Serial Monitor) when inserted in the breadboard. That is. Them run OK when I let them just hanging from the USB cable.

I tested two of them in different breadboards. I also tested the breadboard for shorts and failed connections with an ohmmeter.

These are culprits:
> 0 votes

---
Tags: i2c, nodemcu, wire-library
---


title: Data not updated in real time

text:
# Question
Title: Data not updated in real time
In my recent project, working with JSON and Arduino. Till now, I am getting proper JSON data and add this one into Arduino data. But here I face one problem. My data are not updated in real time.

For example, my JSON string is:

```
{"TPS_Json":"0.40"}

```

And below is my Arduino code:

```
#include<LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false, finished;

//------------------------------ Variable ---------------------------------//

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

  lcd.begin(16, 2);
}

void loop()
{
  //----------------------------TPS----------------------------//

  float TPS = analogRead(A0) * (5.0 / 1023.0);

  //-----------------------JASON DATA--------------------------//

  StaticJsonBuffer<100> jsonBuffer;

  while (finished == false)
  {
    if (Serial.available())
    {
      const char in = Serial.read();
      if (in == '{')
      {
        response = "";  // Blank the string
        begin = true;
      }
      if (begin)
      {
        response += (in); // Only write if within the {}
      }
      if (in == '}')
      {
        begin = false;   // Prevent any chars between } and { leaking through.
        break;
      }
    }
    delay(1);
  }

  JsonObject& root = jsonBuffer.parseObject(response);

  float TPS_Json = root["TPS_Json"];

  float TPS_Final = TPS + TPS_Json;

  lcd.setCursor(0, 0);
  lcd.print("      ");
  lcd.setCursor(0, 0);
  lcd.print(TPS);
  lcd.setCursor(8, 0);
  lcd.print("      ");
  lcd.setCursor(8, 0);
  lcd.print(TPS_Json);
  lcd.setCursor(0, 1);
  lcd.print("      ");
  lcd.setCursor(0, 1);
  lcd.print(TPS_Final);
}

```

So, now I add `TPS_Json` with `TPS`. Where `TPS_Json` is JSON data and `TPS` is an analog value from `A0`. And `TPS_Final` is the addition of `TPS_Json` and `TPS`. I displayed all this on LCD.

Suppose, `TPS_Json = 0.40`, `TPS = 2.40`... So addition is 2.80 means `TPS_Final = 2.80`... And this all data displayed on LCD successfully.

But when I changed my analog value means TPS value then it is not updated and I'm not getting the correct result.

Suppose, I change the value of TPS means makes it `3.00` from `2.40` than my `TPS_Final` must be `3.40`.But nothing updated. It updated when I send JSON data again. I don't know why this happens. I want to change it in real time means When I changed `TPS` then `TPS_Final` must be changed in real time.

# Answer
The reasons it's not updating is because your code is sitting in the loop `while (finished == false) {...}` waiting for more json to arrive.

Try replacing the while loop with something along these lines:

```
  while ((finished == false) || Serial.available()) {
   if (Serial.available()) {
    const char in = Serial.read();
    if (in == '{')  {
        response = "";  // Blank the string
        begin = true;
        finished = false;
    }
    if (begin)
        response += (in); // Only write if within the {}
    if (in == '}') {
        begin = false;   // Prevent any chars between } and { leaking through.
        finished = true;
    }
   }
  }

```

and change the initial variable declarations at the start of the code to set finished to false:

```
// personally I always put each variables on a separate lines when setting initial values.
bool begin = false;
bool finished = false;

```

This will block until it's received at least 1 json string. After that it will check if there is new data on the serial port, if there is it will block until it's received the whole string, it there isn't any data waiting it will exit.

Oh and your response string is currently including the { } characters at the start and end, this contradicts your comments which imply that it doesn't.
> 1 votes

# Answer
Your code reads data from the serial interface and once it has read the input it re-evaluates the value of TPS\_Final. I've found it difficult to understand your question but I think you are saying this:

If you enter `{"TPS_Json":"0.40"}` in the serial monitor and `A0` has a value that equates to 2.4 then you expect TPS = 2.80 on your LCD. So do I.

Now if you change what ever is feeding `A0` so that the value equates to 3.00 I think you are saying you expect you LCD to update to say TPS = 3.40, but it doesn't and you don't understand why.

**IF** that is the case then the answer is simple. When you change the value for `A0` you code is waiting for you to enter the serial data again, because it is a 'blocking function call' well a 'blocking' bit of code at any rate. And until you enter a value in the serial monitor you code won't evaluate TPS again.

You need to change/remove the while loop so it your code will update the LCD even when the data is being entered by the serial interface.
> 0 votes

---
Tags: arduino-uno, node.js, serial-data, json
---


# Question
Title: Arduino UNO IR blaster - storing codes in PROGMEM
I've setup an IR LED on my UNO, with the IRremote library, and have the code working to control an RGB LED strip from certain serial input, however as i'm storing the Raw infrared data in variables, i'm running out of RAM very quickly, and haven't managed to get code working that stores the IR data in PROGMEM, then buffers it to RAM for sending.

The current working code can be found at https://gist.github.com/dan-r/71294eaf9fe2354f1a0c7c13fc5f3bcd, and i've tried setting the int arrays as statics in PROGMEM, but whatever I do, I can't figure out how to buffer them into RAM, or even directly send them with irsend.

# Answer
The Arduino Uno can not read data from PROGMEM (data in flash memory) in the same way as reading data from ram, there are special functions to read data from PROGMEM.

Create a buffer in ram and use one of those special functions to copy the data into that buffer.

Start with the Arduino PROGMEM reference.
Nick Gammon had made a great tutorial about PROGMEM.
All the PROMEM functions are in \<avr/pgmspace.h\>

Is the array of numbers always the same length ? That would make the sketch a lot easier.

Then perhaps something like this:

```
const unsigned int irTable[9][67] PROGMEM = { { ... }, { ... } }

unsigned int irBuf[200];

i = ...   // number of command
memcpy_P ( irBuf, &irTable[i][0], 67 * 2);
irsend.sendRaw (irBuf, 67, ...);

```
> 1 votes

---
Tags: arduino-uno, ir
---


# Question
Title: Is it ok to declare variables inside timer interrupts?
I am building a real time audio application using the Arduino DUE. This application needs big arrays like:

```
uint16_t sDelayBuffer0[46000];

```

The Due has only 96kb of RAM available so this array just ate up most ot its memory. The problem is i need more arrays like this...

So, i was thinking, instead of declaring all of the arrays as global variables, to declare them inside the timer interrupt functions.

The loop() handles stuff like reading the ADCs. The actual effects are coded inside timer iterrupt funciton that are replayed over and over. So the code constantly loops in loop() and the selected timer interrupt function.

But other timer interrupt fucntions use other arrays. So i was thinking to declare every array that a corresponding timer interrupt function wants inside that fucntion.

So all arrays are not declared at the same time (since when we exit the timer interrupt function we were on and head either to loop or another interrupt function, the grabage collector will destroy the array right?)

The problem with this theory, is that this is a real time audio application. So is it wise to constantly declare a big array like this? Since the timer interrupt ficntion will run very very often. Won't i have delay problems iwth the actual sound? Or variable declarations happen extremely fast inside the CPU, even for big arrays?

# Answer
> The problem is i need more arrays like this...

you probably want to take a look at your processing flow to see if you need all of them at the same time. if you do, well, there is no alternative but to get a bigger chip.
> 2 votes

# Answer
First, I don't think it's a good idea to use 46000 * 2 = 92000 bytes of SRAM. That leaves only around 4K left. I hope you don't use a big stack trace, local variables or other global variables.

I don't know if creating an array costs a lot of space, anyway, constantly creating and removing arrays (in heap space) will make your free memory space a mess. This means, that after some time you cannot allocate arrays anymore, especially big ones which need consecutive memory.

Also, within interrupts the code should be as least as possible.

I suggest you use some arrays and reuse them for different reasons. Keep the name simple (like buffer), and reuse the array when needed, without the need to declare it and destroy it. This keeps your memory clear. Make sure the size is big enough for the maximum/worst case you use it for.

Update:

The above mostly assumes that the arrays are made in heap space, not as local variables. However, using local variables is ok.

But anyway, if you need a 2-byte 46000 array, don't expect to be able to use more arrays. In that case use external SRAM (like 23K256, 23LC1024).
> 0 votes

---
Tags: interrupt, timers, array, variables, sram
---


title: High Speed Thermocouple Readings

text:
# Question
Title: High Speed Thermocouple Readings
I'm currently attempting to take readings from 10 thermocouples using an Arduino Mega. I've been using MAX31850 1Wire Thermocouple Modules (with the Adafruit breakout) to perform the readings, but their response time has been very slow (~500ms each). I'm not sure if most of this latency is coming from the IC, or from the communications protocol, or perhaps even the DallasTemperature library.

For my application, I need to be able to read all 10 thermocouples in at most 250 ms (and faster would be better) and so I can afford up to 25ms per thermocouple. I would also like to be measuring with a precision of about 1-2 F.

I assume I will probably have to use a different amplifier, and I've seen recommendations online of using an external ADC to achieve higher speeds, which I would be happy to do, but I don't understand why that would make a substantial difference on speed since the onboard ADC can already sample at about 1/10 ms.

I would greatly appreciate any recommendations on how to achieve these speeds.

# Answer
> 1 votes
From Table 6 on page 22 of the data sheet for MAX31850 1Wire Thermocouple Modules, it appears that about 30 bytes of data are sent per reading (5 command bytes, 9 scratchpad data bytes, 2 x 8 module-id bytes). At an apparent minimum of 60 μs per bit, those 30 bytes will take about 15 ms; at times of say 100 μs per bit, they would take about 24 ms.

Each reading also sends 3 each reset and presence-detect signals, adding up to a few milliseconds, and each reading requires a conversion time *tCONV* of typically 72 ms, per the last entry on page 4 in the *Thermal Characteristics* table.

Thus, it looks like the MAX31850 will take at least 87 ms per reading, if your units are all on the same 1Wire bus and you code things efficiently. (Single units on a bus can use a slightly simpler protocol, which might reduce communication times to perhaps a third as much, but the typical *tCONV* would still dominate the time per reading.)

You might consider attaching an inexpensive Arduino Nano, Micro, or Mini to each of your MAX31850 units. Each of those could communicate with its own MAX31850, allowing all the MAX31850s to convert simultaneously. The small Arduinos could send results to the Mega by I2C or serial, in assigned time slots or upon request from the Mega.

# Answer
> 1 votes
1-wire transmission takes ~100us/1bit so 1ms/byte. so unless the adc is that slow, it shouldn't take you anywhere close to 500ms to take 1 reading, even if you factor in the overhead / reset.

there are dedicated chips but as you mentioned putting an amplifier (instrumentation amps for example) isn't that difficult. simpler with chips with built-in PGA + differential adc. My favorite here are some of the AVR chips (ATtiny85 or ATmega32U for example). But lots of Freescale / STM32F3 chips also work, so long as you are willing to dive into their and roll your own. Lots of fun.

# Answer
> 1 votes
The onboard ADC of the Arduino Mega 2560 is only 10 bits. An external ADC in a thermocouple chip with a fast SPI interface is probably the best solution.
The Adafruit MAX31855 module seems to be able to do that.

The MAX31855 has a 14 bit ADC and a 5 MHZ SPI interface.
It needs a conversion time of 70ms. I think that is normal for these chips. I did not read the datasheet well enough how to get a value without waiting for it.

---
Tags: arduino-mega, sensors, temperature-sensor, adc
---


# Question
Title: Help with code. Fade in LEDs from off (shift register)
I used this tutorial here and decided it to overcomplicate the pattern. For further learning. My code in theory should start the LEDs at a low brightness and fade them in using this code. My expected output is as follows.

> All 8 LEDs start out as off.
>
> Fade in slowly.
>
> LEDs turn of one by one from left to right.
>
> LEDs turn on one by one right to left.
>
> Fade out.
>
> Repeat.

This is the loop that fades the LEDs in.

```
for (byte b = 1; b < 255; b++) {
  setBrightnessUp(b); //sets the brightness up function
  delay(20);
}

```

This is the function:

```
void setBrightnessUp(byte brightness) {// 0 to 255
  analogWrite(outputEnablePin, brightness);
}

```

However at this time it appears to be getting into my loop but not increasing the brightness at all. When the code first runs, the LEDs are on but at a minimum brightness. The rest of the code including the fade out at the end works fine.

Fade out functions:

```
for (byte b = 255; b > 0; b--) {
  setBrightness(b); //sets the brightness function
  delay(20);
}

void setBrightness(byte brightness) { // 0 to 255
  analogWrite(outputEnablePin, 255 - brightness);
}

```

Here is the complete code. Excuse the over commenting it helps me learn:

```
//sets pin out for control pins on shift register

int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
int outputEnablePin = 3; //enables a PWM pin output

//uses byte (8bit binary variable)
byte leds = 0;

void setup() {
  // sets the pins to output mode
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode (outputEnablePin, OUTPUT);
}

void loop() {
  //attempted to make led fade in from 0
  leds = 0; // set led to no output ready for dimming effect
  updateShiftRegister(); //calls the function used for output
  delay(1000); //troubleshooting delay
  for (byte b = 1; b < 255; b++) {
    setBrightnessUp(b); //calls the brightnessup function
    delay(20);
  }
  leds = 255; //Sets the byte variable to 255 or 11111111
  updateShiftRegister(); //calls the function used for output
  delay(500); //waits 1/2 second

  //sets a variable i at 8 and runs while i is more than 1
  //minus 1 each loop
  for (int i = 8; i > -1 ; i--) {
    //Bitclear acts on a byte like its an array
    //it sets the bit at position i to 0 (or off)
    // the left most bit is 7 the right most 0
    bitClear(leds, i);
    updateShiftRegister(); //calls the display function
    delay(250); // waits
  }
  //sets a veriable i at 0 and runs while is less than 8
  //plus 1 each loop
  for (int i = 0; i < 8 ; i++) {
    //same as bitclear but turns on the bit at position i
    bitSet(leds, i);
    updateShiftRegister(); //calls the display function
    delay(250); //waits
  }
  //After the 2 other for loops are finished this will then fade
  //the LEDs out
  //sets the bite to 255 (11111111), while its more that 0
  //and minus 1 each loop
  for (byte b = 255; b > 0; b--) {
    setBrightness(b); //calls the brightness function
    delay(20);
  }
}

// this function outputs the data to the shifter
void updateShiftRegister() {
  digitalWrite(latchPin, LOW);//sets the latch pin to low(off)
  shiftOut(dataPin, clockPin, LSBFIRST, leds);
  // the first 2 functions set the data and clock pins needed
  //to receive data. The LSBFIRST tells it to start at the right
  //most bit (MSBFIRST is oposite). LEDs is our binary array (byte)
  // EG 0000000 would print no lights. It shifts this into the
  //shiftregister at 1 bit at a time from one end or the other
  //(determined by LSBFIRST or MSBFIRST)
  digitalWrite(latchPin, HIGH);  // sets the latch pin to high
  //the low to high state change triggers the output
}

//brightness down slowly
void setBrightness(byte brightness) { // 0 to 255
  analogWrite(outputEnablePin, 255 - brightness);
}

//supposed to fade the brightness up
void setBrightnessUp(byte brightness) { // 0 to 255
  analogWrite(outputEnablePin, brightness);
}

```

Board layout

# Answer
I was mistakenly thinking that setting the brightness variable to 255 would mean that the LED is full on. This is wrong, 255 is actually off.

So with a little change in my code.

```
for (byte b = 255; b > 0; b--) {
  setBrightnessUp(b); //calls the brightnessup function
  delay(30);
}

```

The loop now works. I am still not sure why 255 is off and not on though.
> 1 votes

---
Tags: arduino-uno, code-review
---


title: SdFat Library what is dir_t*?

text:
# Question
Title: SdFat Library what is dir_t*?
I'm using the SDFat library and the `FatFile` type has the functions:

> `bool FatFile::dirEntry(dir_t* dir)`
>
> Return a file's directory entry.
>
> **Parameters**
>
> > \[out\] **dir** Location for return of the file's directory entry.
>
> **Returns**
>
> > The value true is returned for success and the value false is returned for failure.

And

> `uint8_t FatFile::dirName(const dir_t *dir, char *name)`
>
> Format the name field of dir into the 13 byte array name in standard 8.3 short name format.
>
> **Parameters**
>
> > \[in\] dir The directory structure containing the name.
> >
> > \[out\] name A 13 byte char array for the formatted name.
>
> **Returns**
>
> > length of the name.

From what I understand, I should be able to pass something like this into the functions:

```
dir_t Bass;
char dName [13];
FatFile BrowseFile;
BrowseFile.open("/Folder1/File1.txt", O_RDONLY);
Serial.print(BrowseFile.dirEntry(&*Bass));
Serial.print(BrowseFile.dirName(Bass,*dName));
Serial.println(dName);

```

to which the program should output

```
1
[Folder1's 8.3 name length]
[Folder1's 8.3 name]

```

However, I'm getting an error and I can't find any included examples that use these two functions in a sketch. if someone could explain what I'm doing wrong, it would be greatly appreciated.

# Answer
> 2 votes
`dir_t *` is a pointer to a variable of type `dir_t`.

I don't know the API to which you refer, but the format for passing it would be:

```
dir_t Bass;
char dName[13];
BrowseFile.dirEntry(&Bass);
BrowseFile.dirName(&Bass, dName);
Serial.println(dName);

```

# Answer
> 2 votes
> what is dir\_t\*?

a pointer to a data type called dir\_t -\> it must have been defined somewhere in your code/libraries used.

---
Tags: arduino-mega, programming, sd-card
---


# Question
Title: Ams1117 worked fine on battery, up in smoke with 12v power supply
I have a circuit that worked fine on a a 12v lead acid battery for a day. Once connected to a 12v 3a power supply it didn't work properly and then the ams1117 5v burned up and so did a 3.3v one within a few minutes. The 12v power supply is a cheap Chinese model from eBay. My meter shows 12.3v but I don't have a scope. I understand that ripples in the output of the power supply have probably caused this but what does that mean and how has it exceeded the rating of the converter? Is there a simple fix so I can use the power supply? Would a 12v motor or relay be susceptible to the ripples? I'm going to run my esp8266 from a different source but I'd like to keep using the power supply for the motor and 12v relays.

# Answer
> 2 votes
Running an Arduino board with 12V is almost always too much. With only a few leds the voltage regulator on the Arduino boards gets too hot.

The best voltage is 7.5V. Then the voltage regulator has only little power dissipation and it is just high enough to turn off the USB 5V power.
Or power the Arduino board with a 5V (from a USB charger, or USB power pack) to the USB connector.

Never use a power supply that is not certified. It is a safety risk that can be avoided with a few dollars more.
The cheap power supply can have ripples, but it can for example have noise in the MHz range, or a voltage spike when turned on, or voltage overshoot when more current is required. There can also be a coupling to the mains as @Majenko wrote. I have had a few of those. Nasty stuff!
Even with a scope, you can not tell if the power supply is really okay.

If you have a unreliable power source or a voltage that is too high, then a DC-DC converter can convert it into a nice steady voltage.
However, you should first get rid of that cheap power supply and buy a good one.

# Answer
> 0 votes
> ripples in the output of the power supply have probably caused this

probably not. calculate the power dissipation on the regulator and check against its datasheet to see how much temperature rise it was going through. that would help you avoid the same mistake next time.

---
Tags: power, voltage
---


# Question
Title: How can I pass a long as parameter and get a char array in return?
I kind of new to C++, so I'm not sure how to perform such casting.

Example:

```
long myLong = 12345L;
convertToCharArray(myLong); //returns an array with the digits of myLong

```

BTW I'm working with Arduino IDE.

# Answer
> 3 votes
As with many things in C there are many ways of skinning this particular cat.

All of them rely on you first having made a character array to store the result in - you can't "return" an array from a function.

The simplest, though non-standard, way is to use `ltoa()`, which is an avr-libc specific function (not part of the standard libc functions):

```
long myLong = 12345L;
char myCharArray[10]; // Enough room for the answer + 1 NULL char

ltoa(myLong, myCharArray, 10);

```

The `10` in that function call defines the base to represent the number in - base 10 in this case: decimal.

Another way, which is more portable, is to format the string using `snprintf()`:

```
snprintf(myCharArray, 10, "%dl", myLong);

```

In this case the `10` is the maximum length of string to prevent it overrunning the 10-character array we made.

A pure Arduino way of doing it would be to use the dreaded `String` class:

```
String myString = String(myLong);
myString.toCharArray(myString, 10);

```

Again in this example the `10` is the length of the buffer we are copying in to.

And there are more. You could do it manually, character by character using division and modulus operators, for example.

# Answer
> 0 votes
This is a job for pointers.

```
long myLong = 12345;
char* myCharArray = (char*)&myLong;

```

Now pointers and arrays work the same. So you can now use myCharArray\[0\] to refer to the first byte and myCharArray\[1\] for the second etc.

# Answer
> 0 votes
You might be looking for a function that returns the textual representation of a long number. In that case there is actually an AVR standard library function (avr-libc:stdlib.h ltoa):

```
const size_t BUF_MAX = 32;
char buf[BUF_MAX];
const int RADIX = 10;

long myLong = 12345L;
ltoa(myLong, buf, RADIX);

```

The buffer, `buf`, will contain the textual representation of the number, `myLong`, in the given `RADIX`.

Cheers!

# Answer
> 0 votes
Well for such situations I did found a solution.

To convert Float or Long or int into character array format, we could use `dtostrf()`. Syntax:

```
dtostrf(Source_var, StringLength, numVarsAfterDecimal,destinaton_var)

```

Source\_var = the variable you want to convert (float/int/long)

StringLength = Length of the string (for your case just keep it 1)

numVarsAfterDecimal = required number of values after decimal point(keep it zero for now)

destination\_var = the char variable to where the value must be stored(do not use square brackets).

For converting Long to array follow the below code

```
long myLong=12345L;
char var[5];
dtostrf(myLong,1,0,var);

```

If all goes well

```
Result will be like var[]={'1','2','3','4','5'}

```

I found this function very useful and it had been working great for me. Hope it does the same for you.

For more info on dtostrf() : Link

# Answer
> 0 votes
> I kind of new to C++, so I'm not sure how to perform such casting.

to recast it, just make a char pointer and pointer it to the variable. Fairly simple.

if you want to convert ti ascii, there are numerous ways, each with their own pros and cons.

I wrote a set of conversion routines here: https://dannyelectronics.wordpress.com/2017/07/04/a-very-fast-numeric-to-ascii-conversion-routine/

they are designed to convert 8 digit unsigned long to ascii but can be easily rewrite to convert 5 digit.

---
Tags: c++
---


title: Analog thermistor readings are wrong

text:
# Question
Title: Analog thermistor readings are wrong
There are some discrepancies between what is read by the analog channel for a thermistor, ohms values directly obtained on the thermistor using an ohmmeter, and another digital temperature sensor.

**Figure 1:** Left column (y axis) is degree Celcius; x axis is time (minutes). Orange is what was read by the analog channel (thermistor); in yellow the reading by a commercial digital sensor; and in green, manual readings of the thermistor using a ohm-meter.

A bit more context, we are building a simple system to read the temperature from a thermistor via an analog channel. Code algorithm is very similar to what is found here and the electronic layout inspired from here. When we ran into problems, we just went back to the working basics as instructed by those two above-mentioned references.

Pad resistor is 7K Ohms @ +/-1%, measured resistance was 6690 ohms Thermistor is 2252 Ohms @ 25 degree Celsius. Coefficients are as follow, coefficient were solved following a calibration in a thermal bath:

* COEFF\_A = 0.0014644
* COEFF\_B = 0.00023888
* COEFF\_C = 9.8996E-08

Specs from vendor are here (PDF) factory coefficient are about the same. I tried to calculate with either factory and in-house calibrated and there is a few thousandth of a degree of difference between the two - not enough yet to explain the current problem

While investigating I saw some sketch with the same resistance for pad resistor and thermistor, but have seen other differing thus assume this is not an issue.

To troubleshoot and isolate the origin of the discrepancies of the orange line VS other reading, we used

1. other thermistors (every single one behave similarly as the orange line in the figure 1)
2. other digital temperature sensors (every single one behave similarly as the yellow line in the figure 1)
3. we try to put 2 analog thermistors and 2 digital temperature sensors on the same arduino - analog were consistant between each other (discrepancies) and the digital one were behaving as expected (correctly)
4. we switched the pad resistor, no effect
5. other arduinos (did not changed anything, every single one was repeatedly demonstrating the same behaviour )
6. used the system in a temperature controlled room and the discrepancy was still present for the analog channel and absent for the digital sensor.

To be clear, **green** and **yellow** are what we think is the 'real' temperature; and the **orange** is the discrepancy. About 1 - 2 degree differences

We used the raw analog value read by the arduino as an input to manually feed and solve the Steinhart–Hart equation (like using IPYTHON and by hand) and output is the same as the orange line. Did the same with the thermistor obtained by the ohm-meter (Green dots on figure).

**What should be investigated** next to solve the discrepancy between what is read by the analogue channel connected to a thermistor and what the same thermistor provide to the ohm-meter?

Sketch follows

```
#define THERMISTORPIN_0 0               // analog pin 0 on the board
#define SERIESRESISTOR_0 6990             // balance/pad resistor value (ohm)
#define THERMISTORNOMINAL 2252          // resistance at 25 degrees C
#define ZEROABS -273.15                 // zero Kelvin (Celsius)

#define COEFF_A 1.4644E-03          // Coefficient A for Steinhart-Hart eq.
#define COEFF_B 2.3888E-04          // Coefficient B for Steinhart-Hart eq.
#define COEFF_C 9.8996E-08          // Coefficient C for Steinhart-Hart eq.

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

void loop()
{
    float temp1;
    temp1 = Thermistor(analogRead(THERMISTORPIN_0),SERIESRESISTOR_0);
    Serial.println(temp1);
}

float Thermistor(int RawADC, long padResistance) {
  long Resistance;
  float Temp;
  Resistance = padResistance / ((1023.0 / RawADC) - 1);
  Temp = log(Resistance);
  Temp = 1 / (COEFF_A + (COEFF_B * Temp) + (COEFF_C * pow(Temp,3)));
  Temp += ZEROABS;

  return Temp;
}

```

# Answer
> 4 votes
One possibility that has not been mentioned yet: the issue may be the calibration of your ADC converter. Your code carries the implicit assumption that the voltage you measure is

```
V = Vref × RawADC ÷ 1023

```

The correct formula is

```
V = Vref × (RawADC + offset) ÷ scale

```

where `offset` is ideally 0 and `scale` is ideally 1024 (and not 1023, as you are assuming). Since you are looking at relatively small discrepancies, the “ideal ADC” assumption may not be a good enough. I have calibrated 3 Arduino ADCs and found offsets between 2.2 and 2.4, and scale factors between 1026.1 and 1026.3. Thus, if you have an accuracy issue, I recommend you calibrate your own ADC.

As a side note, you could expect slightly better accuracy if the thermistor and the resistor are closer in resistance. Right now you have a factor 3, which is not that bad, but you could use a 2.2 kΩ resistor, which is a very standard value.

# Answer
> 3 votes
So far I can see nothing wrong.

This is all about accuracy and being precise. That is how to deal with this problem. This is not a quick fix.
For example the resistor value has been: 10k, 7k, 6690 and 6990. That's too sloppy.
I think that you have not told us that the thermistor is at GND (I prefer it being at GND, that's good).

**Test**: At 25 °C the thermistor and resistor result in a ADC value of 249.5, and with that in the sketch the result is 25 °C. Very nice. Around 25 °C the sketch is accurate.

Instead of a short minimalistic calculation you could calculate everything. For example the resistance of the thermistor and the voltage at the analog pin. That would make it easer to check those values with a multimeter.
I prefer to let the Arduino do the calculation, and not trying to be smart and optimize something. Let the compiler to the optimizations.

We have to **look further** than the thermistor, the Arduino and the sketch.

1. How long is a long wire ? What kind of cable ? Shielded cable ? Is one wire connected to GND ? and at the end is only the thermistor ? The GND is not used for something else ? Are the wires of the thermistor or the cable touching a metal object or water ? A multimeter is not connected to something, but an Arduino is connected via the usb to the computer and perhaps to earth ground. With a power supply, there is a small capacitive coupling to the mains. What happen if the Arduino is battery powered and not connected to something ?
2. How well is the wire connected to the Arduino. Try to solder it if possible. If it is already soldered, was it a good weld ?
3. What else is going on with the Arduino board ? It could be GND offset caused by something that pushes current through the GND. A LCD display with its background light connected in the wrong way could cause this. Is the thermistor connected via a breadboard, and there is something else on that breadboard ? Then you have almost certainly a DC offset.
4. Could you try with another Arduino board and another computer ? Only the Arduino board, the thermistor + resistor and a USB cable to the computer. Without the long wires. Try a desktop computer, not a laptop (the usb 5V of a laptop could be less reliable). You are now caught in some kind of trap, and you get out by making a second test setup with a new set of components and not even using a single wire from the first setup.
5. The NTC could cool down via the metal legs.
6. Perhaps averaging a number of samples would help. When the final average calculation is done with float, you could even increase the resolution beyond 10 bits of the ADC.

For now, I think that the problem is between the thermistor and the microcontroller on the Arduino board. Could you try to eliminate any DC offset of the GND and be sure to isolate the thermistor (from metal objects and water)

# Answer
> 0 votes
there seems to be two problems:

1) calibration: the digital sensor / analog sensor may not be calibrated properly - this can account for the gap between the two curves.

2) response time: the digital sensor seems to react much faster than the analog sensor. that could be due to placement, physical attributes (smaller thermal mass for example), ...

---
Tags: programming, analogread
---


title: Serial write skips on Arduino Due

text:
# Question
Title: Serial write skips on Arduino Due
I bought Feetech SCS09 smart servos (also known as SCS009 or SCS0009).

**Please note that these servos are not regular PWM servos, they are devices that communicate with board using Serial connection via device named TTLinker that converts UART to half duplex protocol. So the question is about the problem with serial communication only.**

The seller provided me Arduino library to work with the servos.

The simplest testing sketch looks as this:

```
#include <SCServo.h>

SCServo SERVO;

void setup() {
  Serial2.begin(1000000);
  SERVO.pSerial = &Serial2;
  delay(500);
  SERVO.EnableTorque(1, 1);
  SERVO.EnableTorque(2, 1);
}

void loop() {
  SERVO.WritePos(1, 1023, 4000); // Servo ID:1, rotate to the position:0x2FF
  SERVO.WritePos(2, 1023, 1000); // Servo ID:2, rotate to the position:0x2FF
  delay(4000);
  SERVO.WritePos(1, 20, 3000); // Servo ID:1, rotate to the position:0x000
  SERVO.WritePos(2, 20, 1000); // Servo ID:1, rotate to the position:0x000
  delay(3000);
}

```

**The code works perfectly on Arduino Mega** and allows to independently control servos.

But with Due I have problems: not all commands can be performed. So if compile the code for Due only servo ID1 works, but ID2 do not work at all.

When I add delays between commands the servos started to work

```
    SERVO.WritePos(1, 1023, 4000); // Servo ID:1, rotate to the position:0x2FF
    delay(10);
    SERVO.WritePos(2, 1023, 1000); // Servo ID:2, rotate to the position:0x2FF
    delay(4000);
    SERVO.WritePos(1, 20, 3000); // Servo ID:1, rotate to the position:0x000
    delay(10);
    SERVO.WritePos(2, 20, 1000); // Servo ID:1, rotate to the position:0x000
    delay(3000);

```

When I set delays between 1 and 9 the both servos can work but sometimes skip commands. Servos can skip 1-4 actions and then start to work again. The less delay I set the more random skips I get.

So I think here is some specialities regarding Serial connection on Arduino Due. What It can be? Why delays help to make it working?

By the way I read that Arduino Due can have problems with 1000000 baud rate and I tried different, even significntly less baud rates (for example 38400) with Arduino Due: the result is the same.

I need to explain how WritePos function works in the library

```
int SCSProtocol::WritePos(u8 ID, u16 Position, u16 Time, u16 Speed)
{
    return writePos(ID, Position, Time, Speed, INST_WRITE);
}

int SCSProtocol::writePos(u8 ID, u16 Position, u16 Time, u16 Speed, u8 Fun)
{
    flushSCS();
    u8 buf[6];
    Host2SCS(buf+0, buf+1, Position);
    Host2SCS(buf+2, buf+3, Time);
    Host2SCS(buf+4, buf+5, Speed);
    writeBuf(ID, P_GOAL_POSITION_L, buf, 6, Fun);
    return Ack(ID);
}

void SCSProtocol::Host2SCS(u8 *DataL, u8* DataH, int Data)
{
    if(End){
        *DataL = (Data>>8);
        *DataH = (Data&0xff);
    }else{
        *DataH = (Data>>8);
        *DataL = (Data&0xff);
    }
}

int SCSProtocol::Ack(u8 ID)
{
    if(ID != 0xfe && Level){
        u8 buf[6];
        u8 Size = readSCS(buf, 6);
        if(Size!=6){
            return 0;
        }
    }
    return 1;
}

void SCSProtocol::writeBuf(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen, u8 Fun)
{
    u8 msgLen = 2;
    u8 bBuf[6];
    u8 CheckSum = 0;
    bBuf[0] = 0xff;
    bBuf[1] = 0xff;
    bBuf[2] = ID;
    bBuf[4] = Fun;
    if(nDat){
        msgLen += nLen + 1;
        bBuf[3] = msgLen;
        bBuf[5] = MemAddr;
        writeSCS(bBuf, 6);

    }else{
        bBuf[3] = msgLen;
        writeSCS(bBuf, 5);
    }
    CheckSum = ID + msgLen + Fun + MemAddr;
    u8 i = 0;
    if(nDat){
        for(i=0; i<nLen; i++){
            CheckSum += nDat[i];
        }
    }
    writeSCS(nDat, nLen);
    writeSCS(~CheckSum);
}

int SCServo::readSCS(unsigned char *nDat, int nLen)
{
    int Size = 0;
    int ComData;
    unsigned long t_begin = millis();
    unsigned long t_user;
    while(1){
        ComData = pSerial->read();
        if(ComData!=-1){
            if(nDat){
                nDat[Size] = ComData;
            }
            Size++;
            t_begin = millis();
        }
        if(Size>=nLen){
            break;
        }
        t_user = millis() - t_begin;
        if(t_user>IOTimeOut){
            break;
        }
    }
    return Size;
}

int SCServo::writeSCS(unsigned char *nDat, int nLen)
{
    if(nDat==NULL){
        return 0;
    }
    return pSerial->write(nDat, nLen);
}

```

So the problem is somewhere here: **Arduino Mega works good**, but it seems like Arduino Due have no time for on of the operations.

You can see more info here:

Servo

TTLinker device

Arduino library

# Answer
> 0 votes
I figured out that 250000 baud rate is the only choice for the Arduino Due with these servos. Less baud rates cause skips on Arduino Mega also, so this speed is not enough for fast data transfer.

Higher baud rates work good on Mega too but cause garbage on Due.

So let's summarize: these servos with TTLinker (TXS0108E) work good with Arduino Due at 250000 only and with Arduino Mega at 250000 and higher baud rates.

---
Tags: serial, arduino-due, serial-data
---


# Question
Title: 433Mhz receiver only get values of 0, 1, 2
I have two Arduino Uno and a few sets of transmitters and receivers. I followed some guide on the internet to make them work and that's what I did so far but I still get random values of 0 or 1 or 2, no matter what signals I am trasmitting.

I connected the receiver's VCC to 5v on Arduino; the receiver's data to A0 on the Arduino; the receiver's GND to the Arduino's GND.

I connected the transmitter's VCC to 5v on Arduino; the transmitter's data to on Arduino; the transmitter's GND to the Arduino's GND.

This is the transmitter code:

```
#define dataout 12
#define ledPin 13
unsigned int temp = 0;

void setup() {
  pinMode(dataout, OUTPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {

  digitalWrite(dataout, HIGH);
  digitalWrite(ledPin, HIGH);
  delay(5000);
  digitalWrite(dataout,LOW);
  digitalWrite(ledPin, LOW);
  delay(5000);
}

```

This is the recriver code:

```
const int datain=A0;
#define ledPin 13

int temp = 0;
const unsigned int upperThreshold = 500;
const unsigned int lowerThreshold = 100;

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

void loop() {
  temp=analogRead(datain);
  Serial.println(temp);
  delay(300);
  if(temp<lowerThreshold) {
    digitalWrite(ledPin, HIGH);
  }

  if(temp>upperThreshold) {
    digitalWrite(ledPin, LOW);
  }
}

```

I tried to change the transmitter and receivers. I tried to change Arduino boards. I tried to change analog to digital, nothing worked...

Suggestions?

**Update:**

Here are some pictures of my gear:

This is the output of the receiver when both Arduinos work near each other, there no sync between the signals transmitting and receiving.

> 0 1 0 0 0 0 1 1 0 2 1 2 1 0 1 362 0 1 1 1 1 1 0 2 0 314 2 2 1 0 0 2 1 0 1 2 1 1 2 0 1 1 0 1 1 2 1 0 0 0 0 2 1 0 1 0 0 1 0 1 0 1 1 1 2 2 1 1 2 1 1 1 1 1 0 211 2 0 2 0 0 1 2 0 0 759 1 2 1 1 2 1 2 0 1 16 0 0 1 1 0 0 2 1 1 0 1 2 1 2 0 2 1 0 2 0 1 2 1 1 2 2 1 2 0 0 1 0 1 1 2

This is the output when I tried to disconnect the GND and VCC from the receiver:

> 433 426 431 422 379 367 362 394 405 412 406 394 399 388 356 258 193 438 507 507 499 486 478 473 449 442 431 428 427 424 425 423 422 419 417 414 413 413 409 410

# Answer
> 1 votes
Those cheap 433 MHz RF modules require a (good) library to work. The VirtualWire/RadioHead library is the best.

The VirtualWire library it outdated, but still used.

The RadioHead library has a few bugs fixed, but uses more memory.
Use it in RH\_ASK mode, see the included 'ask' examples.

\[**Update: better quality**\]
Most cheap 433 MHz ASK transmitters work with 3.5 to 12V. They have the longest range at 12V. About 20 meters is no problem with 5V, but if longer range is needed then transmitters that are only made for 5V are better.
The cheap 433 MHz receivers use a coil to tune the frequency. They are very sensitive and they do work well. However, when such a module is placed near metal or close to the Arduino, the frequency might change. Modules that use a crystal for the frequency are better. Sometimes a sensitivity is mentioned (for example -112dBm) but I don't know how reliable that is. When an antenna of 16 cm does not work well, try an antenna of more than a meter.

The transceivers are better for wireless data transfer, but that depends on the use.
Sparkfun has Wireless Buying Guide.
RadioHead has a list of supported transceivers.

The nRF24L01+ are very cheap. I read that every one of them on Ebay or Aliexpress is counterfeit, but the counterfeit chips do work. They work at 3.3V, and are 5V tolerant.

The CC1101, CC2500 and so on are good, but not often used with an Arduino. The same for Si4432, Si4436 and so on. If you know a good library, they are very good transceiver chips.

Adafruit is using the RFM69 a lot. For example the Feather Packet Radio board.

Last but not least: don't forget Wifi and Bluetooth.

---
Tags: arduino-uno
---


# Question
Title: 433 MHZ connection between two Arduino (nano,uno) fails after some time
The goal of this part of my project is to establish a wireless connection between an Arduino nano and an Arduino uno. For this I use 433 MHZ receiver and sender. The nano sends, the uno receives and prints. I have working code and the connection works and I can send, receive and print my message. But at some point the Uno receives just a part of the message and after this point always receives (or prints) just this part of the message:

Nano (sender):

```
#include <VirtualWire.h>
char *msg = "123456789123456789";

```

It is not always 2 digits, sometimes more are received.

I searched for errors. The nano is constantly sending and the uno flips to not receiving the whole message. So I reupload the code to the uno without modification and it works again for a few seconds/minutes, so I guess it's a problem at the receiving end.

Here is my code:

Sender(nano):

```
#include <VirtualWire.h>
char *msg = "123456789123456789"

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

 pinMode(7,OUTPUT);
 pinMode(5,OUTPUT);
 digitalWrite(5,LOW); //GND
 pinMode(6,OUTPUT)
 digitalWrite(6,HIGH); //5V
 vw_setup(5000);
 vw_set_tx_pin(7);
}

void loop()     {
 vw_send((uint8_t*)msg, strlen(msg));
 vw_wait_tx();
 delay(500);
}

```

Receiver(Uno):

```
#include <VirtualWire.h>

int i;
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

void setup() {

 Serial.begin(9600);
 pinMode(5,INPUT);
 pinMode(6,INPUT); // two data inputs, we use just one
 pinMode(7,OUTPUT);
 digitalWrite(7,LOW); //GND
 pinMode(4,OUTPUT);
 digitalWrite(4,HIGH); // 5V VCC
 vw_setup(5000);
 vw_set_rx_pin(6);
 vw_rx_start();
 Serial.println("Starting up");

}

void loop() {

 if(vw_get_message(buf,&buflen)) {
   for(i=0;i<buflen; i++) {
    Serial.print((char)buf[i]);
   }
 }
}

```

It doesn't happen after a certain time or number of messages. I have no clue what could be the problem.

Thanks in advance, Niklas

Edit: Problem seems solved. Changing bitrate from 5000 to 2000 solved the problem, but I don't actually know why.

# Answer
Regarding the hardware problem, there are some advices in the comments. As you wrote, the solution is to reduce the bitrate at 2000 bps.

The remaining question is why the receiver always truncates the message (after a receiving error occurs). The answer is in the definition of the **buflen** parameter of the **vw\_get\_message** function. The page https://www.pjrc.com/teensy/td\_libs\_VirtualWire.html says:

> "buflen" should have the array's maximum size upon input, and upon return the number of bytes actually copied is retured.

Therefore, when a transmission error occurs, the buflen variable returns a smaller number to inform you how many characters are received. If you do not reset the buflen variable to VW\_MAX\_MESSAGE\_LEN before calling vw\_get\_message again, you are telling the library that you expect a smaller number of characters and the function respects that size (thinking that you have a smaller buffer).

In other words, if you want try to receive the full message after a transmission error occured, set the buflen variable to VW\_MAX\_MESSAGE\_LEN before each call of the vw\_get\_message function.
> 4 votes

# Answer
Those cheap 433 MHz RF modules can not handle a high bitrate. There are many different 433 MHz modules and the more expensive modules might be able to handle perhaps 10 kHz.
Every pulse from the receiver generates an interrupt. That means also the software has to be able to keep up with it.

For a basic Arduino board at 16 MHz (Arduino Uno, Nano, Leonardo, and so on) and the cheap RF modules the sweet spot is around 1 kHz to 2 kHz bps. The 2 kHz is a safe value.

The 433 MHz frequency requires in most countries that only 1/10 of the time a transmission might be active and the VirtualWire/RadioHead has overhead. That means that the resulting data speed with 2 kHz bps will be between 10 and 20 bytes per second.

The transceiver modules don't have all these (ridiculous) limitations. They can transmit data at a fast rate. Transceiver modules are for example nRF24L01+ modules, CC1101 modules, RFM69 modules, and so on.
> 0 votes

---
Tags: arduino-uno, arduino-nano, communication, wireless
---


title: 7 segment displays arduino mega 2560

text:
# Question
Title: 7 segment displays arduino mega 2560
I'm trying to use an Arduino Mega 2560 to use 7-segment displays, 6 displays... I use 3 CD4543B to pilot the 6 displays.

It works very well for 4 displays as you can see in this video.

But when I want to use the same circuit for 5 or 6 displays, there is some bug as you can see on this video for 5 displays.

Here is the code that works fine for 4 displays:

```
//définition des broches du premier décodeur
const int bit_A=8;
const int bit_B=9;
const int bit_C=10;
const int bit_D=11;
//définition du brochage du deuxieme decodeur
const int bit_E=22;
const int bit_F=24;
const int bit_G=26;
const int bit_H=28;
//définition du brochage du 3ième décodeur
const int bit_I=40;
const int bit_J=42;
const int bit_K=44;
const int bit_L=46;
//définition des broches des transistors

const int alim_millier=3;
const int alim_centaine=4;
const int alim_dizaine=5;
const int alim_unite=6;

void setup() {
  //les broches sont toutes des sorties
  pinMode(bit_A,OUTPUT);
  pinMode(bit_B,OUTPUT);
  pinMode(bit_C,OUTPUT);
  pinMode(bit_D,OUTPUT);
  pinMode(bit_E,OUTPUT);
  pinMode(bit_F,OUTPUT);
  pinMode(bit_G,OUTPUT);
  pinMode(bit_H,OUTPUT);
  pinMode(bit_I,OUTPUT);
  pinMode(bit_J,OUTPUT);
  pinMode(bit_K,OUTPUT);
  pinMode(bit_L,OUTPUT);
  pinMode(alim_millier,OUTPUT);
  pinMode(alim_centaine,OUTPUT);
  pinMode(alim_dizaine,OUTPUT);
  pinMode(alim_unite,OUTPUT);
  //les broches sont toutes mises à l'état bas
  digitalWrite(bit_A,LOW);
  digitalWrite(bit_B,LOW);
  digitalWrite(bit_C,LOW);
  digitalWrite(bit_D,LOW);
  digitalWrite(bit_E,LOW);
  digitalWrite(bit_F,LOW);
  digitalWrite(bit_G,LOW);
  digitalWrite(bit_H,LOW);
  digitalWrite(bit_I,LOW);
  digitalWrite(bit_J,LOW);
  digitalWrite(bit_K,LOW);
  digitalWrite(bit_L,LOW);
  digitalWrite(alim_millier,LOW);
  digitalWrite(alim_centaine,LOW);
  digitalWrite(alim_dizaine,LOW);
  digitalWrite(alim_unite,LOW);
}

void loop() {
  //fonction principale
  for(int i=0; i<10000; i++) {
    //boucle qui permet de compter de0 à9999(=10000 valeurs)
    afficher_nombre(i);//appelde la fonction affichage avec envoi du nombre à afficher
  }
}

//fonction permettant d'afficherun nombre sur quatre afficheurs
void afficher_nombre(int nombre) {
  long temps;//variable utilisée poursavoir le temps écoulé
  int unite=0,dizaine=0,centaine=0, millier=0;//variable pour chaque afficheur
  millier=nombre/1000;//on récupère les milliers
  centaine=(nombre-1000*millier)/100;//on récupère les centaines
  dizaine=(nombre-(centaine*100)-(millier*1000))/10;//on récupère les dizaines
  unite=nombre-(millier*1000)-(centaine*100)-(dizaine*10);//on récupère les unités
  temps=millis();//on récupère le temps courant
  //tant qu'on a pas affiché ce chiffre pendant au moins 500 milliseconde
  //permet donc de pouvoir lire le nombre affiché
  while((millis()-temps)<500) {
    //on affiche le nombre
    //d'abord les milliers pendant 5ms
    digitalWrite(alim_millier,HIGH);
    afficher_CD(millier);//on appelle la fonction qui permet d'afficher le chiffre millier
    digitalWrite(alim_centaine,LOW);
    digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
    digitalWrite(alim_unite,LOW);//le transistor est bloqué
    delay(5);
    //d'abord les centaines pendant 5ms
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,HIGH);//le transistor de l'afficheur des centaines est saturé, donc l'afficheur est allumé
    afficher_CM(centaine);//on appelle la fonction qui permet d'afficher le chiffre centaine
    digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
    digitalWrite(alim_unite,LOW);//le transistor est bloqué
    delay(5);
    //ensuite les dizaines pendant 5 ms
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,LOW);// transistor est bloqué
    digitalWrite(alim_dizaine,HIGH);//transistor saturé
    afficher_CM(dizaine);
    digitalWrite(alim_unite,LOW);//transistor bloqué
    delay(5);
    //on affiche les unités 5 ms
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,LOW);//transistor bloqué
    digitalWrite(alim_dizaine,LOW);//transistor bloqué
    digitalWrite(alim_unite,HIGH);//transistor saturé
    afficher_UD(unite);
    delay(5);
  }
}

//fonction écrivant sur les premiers afficheurs
void afficher_UD(int chiffre) {
  digitalWrite(bit_A,LOW);
  digitalWrite(bit_B,LOW);
  digitalWrite(bit_C,LOW);
  digitalWrite(bit_D,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_D,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_C,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_B,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_A,HIGH);
    chiffre=chiffre-1;
  }
}

//fonction écrivant sur le second afficheur
void afficher_CM(int chiffre) {
  digitalWrite(bit_E,LOW);
  digitalWrite(bit_F,LOW);
  digitalWrite(bit_G,LOW);
  digitalWrite(bit_H,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_H,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_G,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_F,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_E,HIGH);
    chiffre=chiffre-1;
  }
}

void afficher_CD(int chiffre) {
  digitalWrite(bit_I,LOW);
  digitalWrite(bit_J,LOW);
  digitalWrite(bit_K,LOW);
  digitalWrite(bit_L,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_L,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_K,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_J,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_I,HIGH);
    chiffre=chiffre-1;
  }
}

```

And here the code for 5 displays with "bugs" :

```
//définition des broches du premier décodeur
const int bit_A=8;
const int bit_B=9;
const int bit_C=10;
const int bit_D=11;
//définition du brochage du deuxieme decodeur
const int bit_E=22;
const int bit_F=24;
const int bit_G=26;
const int bit_H=28;
//définition du brochage du 3ième décodeur
const int bit_I=40;
const int bit_J=42;
const int bit_K=44;
const int bit_L=46;
//définition des broches des transistors
const int alim_dm= 3;
const int alim_millier=4;
const int alim_centaine=5;
const int alim_dizaine=6;
const int alim_unite=7;
void setup() {
  //les broches sont toutes des sorties
  pinMode(bit_A,OUTPUT);
  pinMode(bit_B,OUTPUT);
  pinMode(bit_C,OUTPUT);
  pinMode(bit_D,OUTPUT);
  pinMode(bit_E,OUTPUT);
  pinMode(bit_F,OUTPUT);
  pinMode(bit_G,OUTPUT);
  pinMode(bit_H,OUTPUT);
  pinMode(bit_I,OUTPUT);
  pinMode(bit_J,OUTPUT);
  pinMode(bit_K,OUTPUT);
  pinMode(bit_L,OUTPUT);
  pinMode(alim_dm,OUTPUT);
  pinMode(alim_millier,OUTPUT);
  pinMode(alim_centaine,OUTPUT);
  pinMode(alim_dizaine,OUTPUT);
  pinMode(alim_unite,OUTPUT);
  //les broches sont toutes mises à l'état bas
  digitalWrite(bit_A,LOW);
  digitalWrite(bit_B,LOW);
  digitalWrite(bit_C,LOW);
  digitalWrite(bit_D,LOW);
  digitalWrite(bit_E,LOW);
  digitalWrite(bit_F,LOW);
  digitalWrite(bit_G,LOW);
  digitalWrite(bit_H,LOW);
  digitalWrite(bit_I,LOW);
  digitalWrite(bit_J,LOW);
  digitalWrite(bit_K,LOW);
  digitalWrite(bit_L,LOW);
  digitalWrite(alim_dm,LOW);
  digitalWrite(alim_millier,LOW);
  digitalWrite(alim_centaine,LOW);
  digitalWrite(alim_dizaine,LOW);
  digitalWrite(alim_unite,LOW);
}

void loop() {
  //fonction principale
  for(int i=0;i<100000;i++)//boucle qui permet de compter de0 à 99999(=100000 valeurs) {
    afficher_nombre(i);//appelde la fonction affichage avec envoi du nombre à afficher
  }
}

//fonction permettant d'afficherun nombre sur quatre afficheurs
void afficher_nombre(int nombre) {
  long temps;//variable utilisée poursavoir le temps écoulé
  int unite=0,dizaine=0,centaine=0, millier=0, dm=0;//variable pour chaque afficheur
  dm=nombre/10000;//on récupère les dm
  millier=(nombre-(10000*dm))/1000;//on récupère les milliers
  centaine=(nombre-1000*millier)-(10000+dm)/100;//on récupère les centaines
  dizaine=(nombre-(centaine*100)-(millier*1000)-(dm*10000))/10;//on récupère les dizaines
  unite=nombre-(dm*10000)-(millier*1000)-(centaine*100)-(dizaine*10);//on récupère les unités

  temps=millis();//on récupère le temps courant
  //tant qu'on a pas affiché ce chiffre pendant au moins 500 milliseconde
  //permet donc de pouvoir lire le nombre affiché
  while((millis()-temps)<500) {
    //on affiche le nombre
    //d'abord les dms pendant 5ms
    digitalWrite(alim_dm,HIGH);
    afficher_CD(dm);//on appelle la fonction qui permet d'afficher le chiffre dm
    digitalWrite(alim_millier,LOW);//le transistor bloqué
    digitalWrite(alim_centaine,LOW);//le transistor est bloqué
    digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
    digitalWrite(alim_unite,LOW);//le transistor bloqué
    delay(10);
    //d'abord les millier pendant 5ms
    digitalWrite(alim_dm,LOW);
    digitalWrite(alim_millier,HIGH);//le transistor de l'afficheur des centaines est saturé, donc l'afficheur est allumé
    afficher_CM(millier);//on appelle la fonction qui permet d'afficher le chiffre centaine
    digitalWrite(alim_centaine,LOW);//le transistor est bloqué
    digitalWrite(alim_dizaine,LOW);//le transistor est bloqué
    digitalWrite(alim_unite,LOW);//le transistor bloqué
    delay(10);
    //ensuite les centaine pendant 5 ms
    digitalWrite(alim_dm,LOW);
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,HIGH);// transistor est bloqué
    afficher_CM(centaine);
    digitalWrite(alim_dizaine,LOW);//transistor saturé
    digitalWrite(alim_unite,LOW);//transistor bloqué
    delay(10);
    //on affiche les dizaines 5 ms
    digitalWrite(alim_dm,LOW);
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,LOW);//transistor bloqué
    digitalWrite(alim_dizaine,HIGH);//transistor bloqué
    afficher_UD(dizaine);
    digitalWrite(alim_unite,LOW);//transistor saturé
    delay(10);
    //on affiche les unités
    digitalWrite(alim_dm,LOW);
    digitalWrite(alim_millier,LOW);
    digitalWrite(alim_centaine,LOW);//transistor bloqué
    digitalWrite(alim_dizaine,LOW);//transistor bloqué
    digitalWrite(alim_unite,HIGH);//transistor saturé
    afficher_UD(unite);
    delay(10);
  }
}

//fonction écrivant sur les premiers afficheurs
void afficher_UD(int chiffre) {
  digitalWrite(bit_A,LOW);
  digitalWrite(bit_B,LOW);
  digitalWrite(bit_C,LOW);
  digitalWrite(bit_D,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_D,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_C,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_B,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_A,HIGH);
    chiffre=chiffre-1;
  }
}

//fonction écrivant sur le second afficheur
void afficher_CM(int chiffre) {
  digitalWrite(bit_E,LOW);
  digitalWrite(bit_F,LOW);
  digitalWrite(bit_G,LOW);
  digitalWrite(bit_H,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_H,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_G,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_F,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_E,HIGH);
    chiffre=chiffre-1;
  }
}

void afficher_CD(int chiffre) {
  digitalWrite(bit_I,LOW);
  digitalWrite(bit_J,LOW);
  digitalWrite(bit_K,LOW);
  digitalWrite(bit_L,LOW);
  if(chiffre>=8) {
    digitalWrite(bit_L,HIGH);
    chiffre=chiffre-8;
  }
  if(chiffre>=4) {
    digitalWrite(bit_K,HIGH);
    chiffre=chiffre-4;
  }
  if(chiffre>=2) {
    digitalWrite(bit_J,HIGH);
    chiffre=chiffre-2;
  }
  if(chiffre>=1) {
    digitalWrite(bit_I,HIGH);
    chiffre=chiffre-1;
  }
}
//Fin du programme

```

I've been trying for weeks to understand the problem. All displays work fine, and if I adapt the code for 4 displays and try to use any 4 of the 6 displays it works fine (I have tried a combination such as displays: 1, 2, 3, 4 or 2, 3, 4, 5 or 3, 4, 5, 6 or 1, 2, 5, 6, everything works).

Thanks to a conversation on the Arduino forum, I also tried this code for 5 displays but I still have the same problem:

```
//Da
const int bit_A=8;
const int bit_B=9;
const int bit_C=10;
const int bit_D=11;
//Db
const int bit_E=22;
const int bit_F=24;
const int bit_G=26;
const int bit_H=28;
//Dc
const int bit_I=40;
const int bit_J=42;
const int bit_K=44;
const int bit_L=46;
// transistors
const int alim_dizainemillier= 3;
const int alim_millier=4;
const int alim_centaine=5;
const int alim_dizaine=6;
const int alim_unite=7;
void setup() {
  pinMode(bit_A,OUTPUT);
  pinMode(bit_B,OUTPUT);
  pinMode(bit_C,OUTPUT);
  pinMode(bit_D,OUTPUT);
  pinMode(bit_E,OUTPUT);
  pinMode(bit_F,OUTPUT);
  pinMode(bit_G,OUTPUT);
  pinMode(bit_H,OUTPUT);
  pinMode(bit_I,OUTPUT);
  pinMode(bit_J,OUTPUT);
  pinMode(bit_K,OUTPUT);
  pinMode(bit_L,OUTPUT);
  pinMode(alim_dizainemillier,OUTPUT);
  pinMode(alim_millier,OUTPUT);
  pinMode(alim_centaine,OUTPUT);
  pinMode(alim_dizaine,OUTPUT);
  pinMode(alim_unite,OUTPUT);
  digitalWrite(bit_A,LOW);
  digitalWrite(bit_B,LOW);
  digitalWrite(bit_C,LOW);
  digitalWrite(bit_D,LOW);
  digitalWrite(bit_E,LOW);
  digitalWrite(bit_F,LOW);
  digitalWrite(bit_G,LOW);
  digitalWrite(bit_H,LOW);
  digitalWrite(bit_I,LOW);
  digitalWrite(bit_J,LOW);
  digitalWrite(bit_K,LOW);
  digitalWrite(bit_L,LOW);
  digitalWrite(alim_dizainemillier,LOW);
  digitalWrite(alim_millier,LOW);
  digitalWrite(alim_centaine,LOW);
  digitalWrite(alim_dizaine,LOW);
  digitalWrite(alim_unite,LOW);
}

void loop() {
  for(int i=0;i<100000;i++) {
    afficher_nombre(i);
    delay(5);
  }
}

void afficher_nombre(int nombre) {
  long temps;
  int unite=0,dizaine=0,centaine=0, millier=0, dizainemillier=0;
  dizainemillier=nombre/10000;
  millier=(nombre-(10000*dizainemillier))/1000;
  centaine=(nombre-(1000*millier)-(10000*dizainemillier))/100;
  dizaine=(nombre-(centaine*100)-(millier*1000)-(dizainemillier*10000))/10;
  unite=nombre-(dizainemillier*10000)-(millier*1000)-(centaine*100)-(dizaine*10);
  temps=millis();
  while((millis()-temps)<500){
    afficher_CD(dizainemillier);
    digitalWrite(alim_dizainemillier, HIGH);
    delay(5);
    digitalWrite(alim_dizainemillier, LOW);
    afficher_CM(millier);
    digitalWrite(alim_millier, HIGH);
    delay(5);
    digitalWrite(alim_millier, LOW);
    afficher_CM(centaine);
    digitalWrite(alim_centaine, HIGH);
    delay(5);
    digitalWrite(alim_centaine, LOW);
    afficher_UD(dizaine);
    digitalWrite(alim_dizaine, HIGH);
    delay(5);
    digitalWrite(alim_dizaine, LOW);
    afficher_UD(unite);
    digitalWrite(alim_unite, HIGH);
    delay(5);
    digitalWrite(alim_unite, LOW);
  }
}

void afficher_UD(int chiffre) {
  digitalWrite(bit_A,chiffre & 1);
  digitalWrite(bit_B,chiffre & 2);
  digitalWrite(bit_C,chiffre & 4);
  digitalWrite(bit_D,chiffre & 8);
}

void afficher_CM(int chiffre) {
  digitalWrite(bit_E,chiffre & 1);
  digitalWrite(bit_F,chiffre & 2);
  digitalWrite(bit_G,chiffre & 4);
  digitalWrite(bit_H,chiffre & 8);
}

void afficher_CD(int chiffre) {
  digitalWrite(bit_I,chiffre & 1);
  digitalWrite(bit_J,chiffre & 2);
  digitalWrite(bit_K,chiffre & 4);
  digitalWrite(bit_L,chiffre & 8);
}

```

Any clue is very welcome! Thanks!

# Answer
> 1 votes
I think it's because I use `int` and I should use `long` to avoid overflow... for the number I want to display:

```
void loop()
{
 for(int i=0;i<100000;i++)
 {
   afficher_nombre(i);
   delay(5);
 }
}

```

should be :

```
void loop()
{
 for(long i=0;i<100000;i++)
 {
   afficher_nombre(i);
   delay(5);
 }
}

```

And also a parentheses problem solved thanks to cattledog on this forum

# Answer
> 0 votes
> Here is the code that works fine for 4 displays:

both code pieces suffer from the use of "delay()".

here is what I used - https://dannyelectronics.wordpress.com/2017/06/30/a-more-flexible-driver-for-7-segment-leds/

it is written so the leds can be driven by individual pins so porting to arduino requires no change to the source code - just a few macros to remap the IO operations.

also running it from a timer isr is the (only) way to go.

edit: here is to show how the code above gets to work here. I expanded it to cover 8 digits but only the first 6 digits effective. three macros are all it takes to repurpose it for arduino.

displaying a fixed "123456".

all the user code does is to dump the content to be displayed into the display buffer and the display routine, led\_display() takes care of the rest.

---
Tags: display, atmega2560
---


# Question
Title: Arduino Due not properly detecting SD card
I have an SD breakout for my Due that isn't properly detecting the SD card. On one card, it cannot detect at all, and the other it says that the SD isn't formatted with FAT, even though it is. Here is my wiring:

simulate this circuit – Schematic created using CircuitLab

So, I broke out my oscilloscope and started probing lines. One in specific I got worried about, is the SCK line and it's bouncing, specifically from the inductance of the jumpers. This is the SCK line from my scope:

My reaction was to put some buffer caps on there, and so I put 2x 300pf capacitors in parallel for a total of 600pf. This is the waveform as measured after I put in the debouncing caps:

This is much more tolerable, and I can accept this level of bouncing for the SCK line, as I doubt that there will be much misfiring. I upload the `SD card test` sketch that's on the website, here is the output:

```
Initializing SD card...Wiring is correct and a card is present.

Card type: SD2
Could not find FAT16/FAT32 partition.
Make sure you've formatted the card

```

What does The Arduino Due have that makes it hard to detect the card?

# Answer
Remove the caps please. Perhaps the scope itself creates the overshoot.

The Due is not special. It should work.

Can you tell what kind of SD memory cards and which SD module you use ?

Try the SD Formatter, see the post at the Arduino.cc forum: "Don't Format SD cards with OS utilities!".
Some SD memory cards are not compatible. Perhaps you have more luck with an older 1GB or 2Gb SD memory card.
> 1 votes

---
Tags: arduino-due, sd-card
---


title: Connect HX711 to a three wire load cell

text:
# Question
Title: Connect HX711 to a three wire load cell
I have the following load cells:

I'm using the following HX711 amplifier

Every guide i can find on the internet describes how to connect a load cell with four wires to the amplifier. How can i connect a load cell with three wires to the amplifier?

Thanks in advance.

# Answer
> 2 votes
A datasheet for the HX711 is https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711\_english.pdf (On your board, it looks like E+ is AVDD and E- is AGND.)

Each of your two load cells could be a half-bridge of a wheatstone bridge, with excitation on the white and black, and sensing on the red like:

I have a similar loadcell with the colors as Blue-Red-Black, (instead of White-Red-Black as above, or the Red-White-Black in your image) with my red sensing wire in the middle. The positive strain resistance (increasing resistance with increasing load) is between the Blue and Red, while the negative strain (decreasing resistance with decreasing load) is between the Red and the Black. The ~1000 ohm resistance in each leg changes by tenths of an ohm with hand pressure on the button, when the outer portion is supported, but the inner portion is not supported. Your cells do not have the bridge-button part that create a balanced twist along the center portion, so it might be hard to reliably apply a load your cell.

To make positive deflections of the cells combine to unbalance the Wheatstone bridge, wire one cell's white and black opposite to the other cell, and attach them to E+ and E-, with the reds connected to A+ and A- like this:

```
   HX711.E+ : Cell1.White + Cell2.Black
   HX711.E- : Cell1.Black + Cell2.White
   HX711.A+ : Cell1.Red
   Hx711.A- : Cell2.Red

```

The labelling on the schematic isn't quite right-- the "Reference 1K" are actually the negative-strain portions of the cells, and might be better labelled as "-Active 1k Ohm".

If it moves in the wrong direction/wrong sign with increasing force, switch the reds or multiply by -1.

If you have only one three-wire cell, use a couple 1K resistors, or a 2K potentiometer to balance the existing cell as the other half of the Wheatstone bridge. One issue with using discrete (10%, 5%, 1%?) resistors is that the precision and tolerances when configured as a voltage divider may produce a significantly different result as compared with the balance in a lead cell and its full-scale signal (+/-0.1%) in a loadcell. A the center tap of a potentiometer can provide for tuning to match the load cell voltage. For the HX711's 32x, 64x, or 128x gain, you need to keep the voltage differences between the sense terminals between +/-80mV, +/-40mV, or +/-20mV to stay within the limits of the HX711.

Per @wirewrap's comment, the colors on the wire could be different than the picture I posted. You can make certain by measuring the resistances between the wires and exciting on the pair with the greatest resistance, and sensing on the middle terminal.

# Answer
> 1 votes
When you have four half bridges I think that you will need to read them separately as pairs and then sum the result in software. I would be interested in hearing how multiple hx711 modules should be best handled by a Nano.

Update. I have discovered that sparkfun produce a load cell combinator board that assists wiring four half bridge load cells to appear as a full bridge. I have still not understood how that works yet.

# Answer
> 0 votes
It seems like that module is used to connect the 4 wire load cell, but on the internet I found other schematics that might help you out how to wire it up.

This is one way (http://i46.tinypic.com/30j0d2t.jpg):

Otherwise try this way:

I am not an expert on load cells but it seems like you just need to give it a try and see if it works.

# Answer
> 0 votes
> How can i connect a load cell with three wires to the amplifier?

it is one-side of the bridge.

the other side can be another load cell or a resistor bridge.

---
Tags: arduino-mega, c++, electricity, analog-sampling
---


# Question
Title: Can I cause breaking the main loop from an interrupt?
Consider this simple approach to make a light work in 3 different modes: on, off and blink:

```
attachInterrupt(buttonVector, switchMode, FALLING);

void loop() {
  switch(mode) {
    case 0: turnOff(); break;
    case 1: turnOn(); break;
    case 2: blinkOnce(); break;
  }
}

```

now if `switchMode` is something like this:

```
unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = 0;
void switchMode()
{
  interrupt_time = millis();
  // debounce measures
  if (interrupt_time - last_interrupt_time > 200)
  {
    mode = (mode + 1) % 3;
  }
  last_interrupt_time = interrupt_time;
}

```

then once the button is pressed, the mode is changed and if we were in the blink mode (`mode == 2`) we'll wait until the blink is done (let's say that's 2 seconds) and only then the mode is actually switched to the "off" mode. Now, can I stop whatever was in the process of current loop, break it and get the "off" instantly?

PS Of'course there can be some workarounds, like

```
void switchMode()
{
  interrupt_time = millis();
  // debounce measures
  if (interrupt_time - last_interrupt_time > 200)
  {
    mode = (mode + 1) % 3;
    if(mode == 0)
      turnOff();
    if(mode == 1)
      turnOn();
  }
  last_interrupt_time = interrupt_time;
}

```

but is there something more elegant and general? (note that if there's 4 modes: on, off, blink, blink\_slowly, than this won't work)

# Answer
No, you can't. An interrupt cannot affect the flow of the existing procedure except by passing data or status to it through a variable.

In multi-threading terms what you are talking about is a *semaphore* \- a shared flag which one thread or context (the interrupt) sets and another thread or context (the main loop) reads and responds to.

If you want to respond to it fast you must write your main loop in such a way that it is possible to respond to it fast.
> 0 votes

# Answer
> but is there something more elegant and general?

there are certainly ways to do what you want to do. whether they are elegant / generic is up to debate. however, they are all well known and widely used so i suppose they are at least accepted.

the simplest would be to prohibit interrupt at beginning of the switch / case block. "mode" will always be atomic.

the 2nd would be a double read on "mode".

```
  do {
    mode_shadow = mode; //save mode
    switch (mode_shadow) {
      case ...
    }
  } while (mode_shadow != mode); //continue to execute the switch block if mode has changed

```

this is a classic case to ensure atomicity without inhibiting interrupts.

the 3rd possible approach is to make the switch / case block dependent on "mode" at each step of execution. this is often used in high reliability computing where you aren't sure if a piece of data you read is ever valid. here you can ensure that through two ways: 1) affirmative: a statement is only executed if "mode" meets expectation. or 2) exclusive: all statements are not executed as soon as "mode" fails to meet expectation. This will drop you out of any of the branches of the switch / case block. atomicity isn't assured in this case but it is only violated for a short period of time.

the last I would mention would be typical of an OS where a "global" variable is maintained so that each task accesses that global variable to know what's going on. RTOS does that via messages for example. Not as real time as approach #1 / #2 above but it is fairly generic.
> 1 votes

# Answer
It is possible. You could use a setjmp()/longjmp() combination, or you could just manipulate the stack in assembly right before returning from the interrupt. This however, makes the program very difficult to reason about, which can easily lead to introducing very hard to find bugs. It is certainly *not* a good solution for your specific problem.

The straightforward solution to your actual problem is to make your loop *non blocking*, and this is achieved with the technique explained in the Blink without delay Arduino tutorial. Your case is a little bit more complex, as your LED can be in three modes. I suggest you consider instead that it can actually be in *four* modes by saying that, while it's blinking, the ON and OFF states are different modes:

```
static enum { OFF, BLINK_OFF, BLINK_ON, ON } mode;

```

I would let the interrupt handler take care of the button-controlled mode switching:

```
void switchMode()
{
    // Debounce.
    static uint32_t last_interrupt_time;
    uint32_t interrupt_time = millis();
    if (interrupt_time - last_interrupt_time < DEBOUNCE_TIME)
        return;
    last_interrupt_time = interrupt_time;

    // Switch modes.
    switch (mode) {
        case OFF:  // OFF -> blink
            digitalWrite(LED_PIN, HIGH);
            mode = BLINK_ON;
            break;
        case BLINK_OFF:  // blink -> ON
        case BLINK_ON:   // ditto
            digitalWrite(LED_PIN, HIGH);
            mode = ON;
            break;
        case ON:  // ON -> OFF
            mode = OFF;
            break;
    }
}

```

And the `loop()` only has to deal with the blinking:

```
void loop()
{
    // This only has to handle the timing of the blinking.
    uint32_t now = millis();
    static uint32_t last_toggle_time;
    switch (mode) {
        case BLINK_OFF:
            if (now - last_toggle_time > TIME_OFF) {
                digitalWrite(LED_PIN, HIGH);
                mode = BLINK_ON;
                last_toggle_time = now;
            }
            break;
        case BLINK_ON:
            if (now - last_toggle_time > TIME_ON) {
                digitalWrite(LED_PIN, LOW);
                mode = BLINK_OFF;
                last_toggle_time = now;
            }
            break;
        default:
            // Nothing to do in the other modes.
            break;
    }
}

```

Another option is to have the interrupt handler only set a flag to signal the button press. Then `loop()` would take care off all mode changes. This can be a good option if you want the “state machine” (the control of the `mode`) contained in a single function.
> 1 votes

---
Tags: interrupt
---


title: Saving sensor logs of unknown length

text:
# Question
Title: Saving sensor logs of unknown length
I have a sensor giving me values (ints) which I want to keep, and send to a computer via the WiFi shield when requested via HTTP. I have the HTTP thing working, however, I do not know how to have a String or whatever able to store what is basically an array of ints, when I do not know any maximum size.

I have read that using Strings on Arduino is not recommended because how RAM works and such things, so I translated all my String uses to C-style arrays (as it was recommended), this solved my memory issues, however, C-style strings are not resizable.

While browsing the forums, I found that for similar problems the recommended way of handling things would be to create an array of max size instead of dynamically growing the array, but I do not know the maximum size in this case.

Here are the requirements

* A way of storing each values (in order) so they can be sent later after an HTTP request (but they can get requested multiple times so I can't delete them then),
* Whatever storage way is fine by me (Strings, arrays of ints, ...), as long as it works.
* A request to the data should take ~100ms (I don't think this will cause issues, but I'll mention it just in case).

I thought about printing the values to the SD card, since there I have far enough memory, but for some reason I can't get the WiFi and the SD card to work together (as soon as I init the SD library, the WiFi library doesn't work anymore - I asked an other question about this here).

PS. I'm quite new to C++ and Arduino, but I'm not too bad at Java.

What would be the best (or at least a working one) way of achieving this ?

# Answer
This is basically two questions: how to get your SD card and WiFi working at the same time (in which case memory limitations are not an issue), and how to deal with the memory limitations if you choose in-memory storage of your data. I'll address the second one here; you should split out the WiFi/SD conflict into a separate question where you detail the exact hardware you're using and how it's connected.

You've got only 2 KB of RAM in an Uno and similar models, so you will have to discard data at some point, whether or not it was successfully sent in a reply to a web request. The key here is to use a fairly compact method of storing the data and to have an easy way to get rid of old values to free up space for new values.

One common way to deal with this is to use a ring buffer. This is a fixed size storage array with a pointer or index, which I'll call *head*, indicating the next storage location to use. You start with *head = 0* (the beginning of the buffer) and every time you receive a new value you store it at *head* and then increment *head* by one. You also need to compare *head* to the end of the buffer and, when it would pass the end, reset it back to the beginning of the buffer. After the first pass through the buffer, storing at *head* will overwrite the oldest value previously stored.

Going back through the buffer to read out the old values is easy: you just start by reading the value at *head - 1* (or the end of the buffer if *head* is 0) and work downwards, wrapping around when you hit 0, and stopping when you reach *head*.

You can handle the initial states where the buffer hasn't been filled yet in two ways: just fill the buffer with a value such as 0 that you don't mind returning as a "nothing stored here" value, or just set a flag at the start to say that the buffer hasn't been filled yet and you should stop at 0 when reading it out; this flag would be cleared the first time that *head* reaches the end of the buffer and wraps around.

Since you're getting data that are ints, storing them as (larger) strings would be silly; just create an array of ints of the smallest type that can store all possible values of your sensor, e.g., `uint16_t` if you're getting unsigned 16-bit values. With some experimentation and checking, you should be able to figure out how large a buffer you can use based on how much storage you have free after the RAM for other parts of the program has been allocated. I'd imagine that if you're careful and you're making sure you store strings in program memory you could make room for a buffer that would hold a couple of hundred entries.

Since this seems to be a student assignment, I won't provide sample code here; writing your ring buffer code will prove an excellent exercise in the details of programming.
> 1 votes

# Answer
> What would be the best (or at least a working one) way of achieving this ?

none. Because the upper end of your possibilities (ie. infinite amount of data) is way beyond anything a computer can possibly handle now and into the distant future.

So unless you have some reasonable upper bound for the data in question, there isn't a whole lot you can do to satisfy your application.
> 0 votes

---
Tags: datalogging
---