body:
I am using a two Arduino setup with two XBee radios. One radio is sending data and the other is receiving data. I am sending three sensor readings following a protocol which uses three bytes for each sensor reading. Byte one is sensor information, byte two is data, and byte three is for error checking. When I run the set up for about 5 minutes I get approximately 47% errors in transmission. When I use the same size output and paste it all into the serial monitor I get 5 errors and all five come with the reading of the last 5 blocks of three bytes. Here is the code to send the data:

            delay(2000);

            // Calcuate weather parameters for serial and web
            calcWeather(); // Go calc all the various sensors

            // send weather out to serial port
            if (prevtemplm34_1 == templm34_1) // 2 in a row must be the same to send
            {
                Serial.write(0);
                Serial.write(templm34_1);
                Serial.write(templm34_1 ^ 0);
            }

            // send weather out to serial port
            if(prevtemplm34_2 == templm34_2) // 2 in a row must be the same to send
            {
                Serial.write(1);
                Serial.write(templm34_2);
                Serial.write(templm34_2 ^ 1);
            }

            // send weather out to serial port
            if(prevtemplm34_3 == templm34_3) // 2 in a row must be the same to send
            {
                Serial.write(2);
                Serial.write(templm34_3);
                Serial.write(templm34_3 ^ 2);
            }
            delay(2000);

The code for parsing received data is:

    int readData ()
    {
    // There must be at least three available bytes to satisfy the protocol
    // Otherwise, wait until three bytes have arrived to read anything
    if (Serial.available() >= 3) {

          // Read the next three byte in the serial buffer
          incomingByteOne = Serial.read();
          Serial.write("Byte One: ");
          Serial.write(incomingByteOne);
          Serial.println();
          incomingByteTwo = Serial.read();
          Serial.write("Byte Two: ");
          Serial.write(incomingByteTwo);
          Serial.println();
          incomingByteThree = Serial.read();
          Serial.write("Byte Three: ");
          Serial.write(incomingByteThree);
          Serial.println();

          // XOR the first and second incoming bytes so that the result can be checked against the third error checking byte
          byte xorValue = incomingByteOne ^ incomingByteTwo;
          Serial.write("XOR VALUE: ");
          Serial.write(xorValue);
          Serial.println("Number of Errors: ");
          Serial.println(numberOfErrors);
          Serial.println();
          Serial.println();
          if(xorValue != incomingByteThree) {
            numberOfErrors++; // Add one to the total count of number of errors in transmission
          }
          else {
            // Mask for retrieving the five rightmost bits from incomingByteOne (00011111)
            byte maskForSensorNumber = 0x1f;

            // Shift incomingByteOne right 5 times in order to obtain the three bits representing the unit number
            int unitNumber = incomingByteOne >> 5;

            // AND incomingByteOne with the mask in order to retrieve only the five righmost bits representing the sensor number
            int sensorNumber = incomingByteOne & maskForSensorNumber;

            // Store the data for the correct sensor on the correct unit
            data[unitNumber][sensorNumber] = incomingByteTwo*1;
         }
    }
    }

It seems like the error is at least partially with my code. What could I do to reduce errors?

title: High rate of transmission errors (~50%) using Xbee Radio

Answers: 0


body:
[![enter image description here][1]][1]

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

I don't know why `CIPSEND` command closed the connection after sending done without `CIPCLOSE` command. Is it normal?

If I want to keep the connection, what should I do in this case?

title: AT+CIPSEND command closed the connection automatically

Answers: 0


body:
Is the [LilyPad Arduino Main Board][1] physically capable of interfacing with, let's say, a [LeddarTech LeddarOne Optical Rangefinder][2], which has a 3.3v UART interface? I understand that the LilyPad has a serial interface, but I wouldn't be sure if it was meant to handle more than just transferring code.

  [1]: https://www.arduino.cc/en/Main/ArduinoBoardLilyPad
  [2]: http://www.robotshop.com/en/leddartech-leddarone-optical-rangefinder-33v-uart.html

title: Can LilyPad Main Board interface with a sensor via UART?

Answers: 1

body:
Yes you can.

Lilypad <> Other device using UART

Rx         <    Tx

Tx         >    Rx

Note that you cannot use 5V with the lilypad if you do this. If you do want to use 5V with the Arduino, then you'll have to put a voltage divider between the Tx and Rx (other wise you might fry the other UART device using 3.3V.

Also, when you upload the code FROM your computer TO your Lilypad, you have to connect all other UART device connected to the Lilypad. Connecting other devices to the Tx and Rx of the Lilypad while uploading a code to it might cause lag or bugs.

Hope I anwsered your question!


body:
I would like to generate a sequence of pulses of varying lengths in the range of 0-100us, so that from the start of one pulse to the start of the next there is a delay of 100us. I have set up timer0 in CTC mode to trigger an interrupt every 100us.

In this interrupt, I would like to turn the appropriate pin high, read the length of the current pulse from an array, and then configure the timer in such a away that it turns the pin off as soon as the pulse length has elapsed (I am hoping that this is possible without using an interrupt for turning off the pin). It seems that the PWM functionality can do what I want, if I use the second output compare register.

In any case this seems possible using a secondary timer in PWM mode, but I'd like to know whether the same is possible using only a single timer. From what I've seen in the datasheets the answer seems no, but perhaps I am missing something.

Can a timer be used in both CTC (with output compare register A) and PWM modes (with output compare register B)?

title: Can a timer be used in both CTC and (fast) PWM mode simultaneously?

Answers: 2

body:
Technically no. CTC and PWM are distinct modes of operation.

*However*, more advanced PWM modes, specifically mode 7 for 8-bit timers and modes 14 and 15 for 16-bit timers, allow specifying an arbitrary timer duration in OCRxA or ICRx while still allowing PWM operation using the other output compares.

body:
As noted in previous answer, CTC and PWM are distinct modes, and only one mode can be selected at any given moment.

However, your problem description sounds like mode 14 on timer 1 will serve.  That's a Fast PWM mode that uses ICR1 as TOP.  OCR1A or OCR1B can be used for output compare, depending whether you want to output on OC1A or OC1B. OC1A is PB1, or digital pin 9 on ATmega328 systems, and OC1B is PB2, or digital pin 10.

On a 16 MHz system, you would put 1600 in ICR1, so there would be an  Overflow Interrupt every 100 μs.  At each Overflow Interrupt you would put the currently desired pulse-length into OCR1A or OCR1B.  This will work so long as your Overflow ISR takes fewer cycles than any desired pulse length.

You would set COM1A1/COM1B1 and COM1A0/COM1B0 to 1, 0, because Table 16-3 for this combination says, “Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode).”  [Or see §16.9.3 (“Fast PWM Mode”) of the 2015 '328 spec, which says: “In non-inverting Compare Output mode, the Output Compare (OC1x) is cleared on the compare match between TCNT1 and OCR1x, and set at BOTTOM.”]


body:
This is my arduino code for interfacing with an ESP8266:

    #include <ESP8266WiFi.h>

    int incomingByte;
    String value;
    char a;
    int flag=0;
    String valueserial;
    int valueint;

    const char* ssid     = "NIDHI";
    const char* password = "nidhi123";

    String data;

    void setup() {
      Serial.begin(9600);
      delay(6000);
      data = "";
      valueserial = "";

    //
      Serial.println();
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);
     //
      WiFi.begin(ssid, password);

      while (WiFi.status() != WL_CONNECTED) {
        delay(500);

        Serial.print(".");

      }
      //
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    //
    }

    void loop() {
      flag = 0;
      delay(5000);
      valueserial = "";
      // Use WiFiClient class to create TCP connections
      WiFiClient client;
    String url = "/display.php";

    if (Serial.available() > 0){
        while (Serial.available() > 0) {
                    // read the incoming byte:
                    incomingByte = Serial.read();
                    valueserial += char(incomingByte);
                  }
        if (incomingByte == '\n') {
          Serial.print("Value:");
          Serial.println(valueserial.toInt());
          Serial.print("String: ");
          Serial.println(valueserial);
          // clear the string for new input:
        }
        //valueint = Serial.parseInt();
        data = "?value=" + String(valueserial.toInt());

        url += data;
        delay(100);
        flag = 1;
    }

    if (client.connect("www.soil.pixub.com",80) && flag==1) { // REPLACE WITH YOUR SERVER ADDRESS
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
        "Host: soil.pixub.com\r\n" +
        "Connection: close\r\n\r\n");
        Serial.println("!!!!DATA POSTED!!!!");
       }

           //valueserial += '\0';
      //valueserial = Serial.read();
    //
    Serial.println(data);
    //
      if (client.connected()) {
        client.stop();  // DISCONNECT FROM THE SERVER
      }
    //
      Serial.println();
      Serial.println("closing connection");
    //
    }

And i am getting the following errors

    Arduino: 1.6.12 (Windows 10), Board: "Arduino/Genuino Uno"

    In file included from C:\Users\Akshay\Documents\Arduino\libraries\ESP8266WiFi\src/ESP8266WiFi.h:33:0,

                     from C:\Users\Akshay\Downloads\esp8266code\esp8266code.ino:3:

    C:\Users\Akshay\Documents\Arduino\libraries\ESP8266WiFi\src/ESP8266WiFiType.h:26:19: fatal error: queue.h: No such file or directory

     #include <queue.h>

                       ^

    compilation terminated.

    exit status 1
    Error compiling for board Arduino/Genuino Uno.

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

title: Error in the arduino code

Answers: 2

body:
[The file queue.h][1] is either missing or is not in the expected location (correctly installed).  Make sure you have your SDK and Libraries correctly installed and up-to-date.  In an extreme case, you might consider reinstalling both to make sure the build environment is correct.

  [1]: https://github.com/esp8266/Arduino/blob/master/tools/sdk/include/queue.h

body:
The ESP8266WiFi library is meant to be used when programming an ESP8266 using the Arduino environment. In Arduino lingo: It's supposed to be used with a ESP8266 Board.

It's -not- meant to be used with a 'Arduino/Genuino Uno' board, which is what you are trying to do. This is why it fails.

What you want to use is the ESP8266wifi library, which is used with a ESP8266 connected to a Arduino, and flashed with AT firmware.

And yes, it's confusing, there are two very similar libraries:

- Programming an ESP8266 using Arduino IDE:

ESP8266**WiFi**: https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi

- Programming an Arduino using Arduino IDE, to communicate with ESP8266 using AT commands:

ESP8266**wifi**: https://github.com/ekstrand/ESP8266wifi


body: As the question, How to get real time data from ardunio board using NodeJS and send to my remote server without the wifi module.how to do this without any hardware.

title: How to get real time data from ardunio board using NodeJS and send to my remote server without the wifi module?

Answers: 1

body:
It is pretty easy to send data with the help of NodeJS. Here i attach the code.

    var request = require('request');
    var serialport = require("serialport");
    var SerialPort = serialport.SerialPort;

    var serialPort = new SerialPort("COM5", {
      baudrate: 9600,
      parser: serialport.parsers.readline("\n")
    });

    serialPort.on("open", function () {
      console.log('open');
      serialPort.on('data', function(data) {
        console.log(data);
      });
    });

    serialPort.on('data', sendSerialData);

    function sendSerialData(data) {
     request({
      uri: "http://127.0.0.1/write_data.php?value="+data,
     method: "GET",
      timeout: 10000,
       followRedirect: true,
       maxRedirects: 10
    }, function(error, response, body) {
       console.log(body);
    });

    }


body:
**BACKGROUND**

I have made my own Arduino PCB based on the circuit of the Arduino Pro Mini (below) (including the external oscillator).
[![Picture of Arduino Pro Mini][1]][1]

I have already written the firmware and the code is stable. The code uses the `millis()` function which uses Timer 0. I also have changed the frequency of the PWM output on pins 3, 9, 10, 11, using the clock select bits (bits 2:0 in TCCR1B & TCCR2B). See http://playground.arduino.cc/Main/TimerPWMCheatsheet

I have an ISP 6-pin programming port on the board and this is my only method of uploading code.

I want minimize on components (and avoid EMC issues), so I have been considering removing the external 16MHz crystal and instead using the internal 8MHz oscillator.

**QUESTIONS**

 1. What do I need to change to use the internal oscillator?

I suspect that I need to change the board.txt file, the clock select bits and the fuses to accommodate for the new frequency.

 2. Can I leave the external crystal in place or do I have to remove it?

 3. If I do leave the external crystal in place and set the fuses to use the internal oscillator, will the crystal continue to resonate or does it get powered down somehow?
(I wish to know this for EMC reasons)

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

title: Change from using the external crystal to the internal oscillator

Answers: 1

body:
> 1. What do I need to change to use the internal oscillator?

You'll need to change the fuses on the chip, and you probably want a new 8MHz entry in `boards.txt` so that timing functions still work as expected.

> 2. Can I leave the external [*resonator*] in place or do I have to remove it?

> 3. If I do leave the external [*resonator*] in place and set the fuses to use the internal oscillator, will the [*resonator*] continue to resonate or does it get powered down somehow?
    (I wish to know this for EMC reasons)

From the datasheet:

> If the Internal Calibrated RC Oscillator is used as chip clock source, PB7...6 is used as TOSC2...1 input for the Asynchronous Timer/Counter2 if the AS2 bit in ASSR is set.

Also:

> When AS2 is set, pins TOSC1 and TOSC2 are disconnected from Port B. A crystal can then be connected between the TOSC1 and TOSC2 pins to serve as an
independent clock source for Timer/Counter2. The Oscillator is optimized for use with a 32.768kHz crystal.

Therefore if `AS2` is not set, the two pins act as normal GPIOs and the resonator is disabled.


body:
Now I have these Arduino Pro Mini from Sparkfun. They are the latest version that I know (yeah, it's the one that have those horrible misaligned pins). Now they are designed around the ATmega328P and have a 16MHz crystal on them.

Now, my question is: Can I run an ATmega328 with a 16MHz crystal while supplying ONLY 3.3V.

The reason I'm doing this is because 5V / 16MHz Pro Minis from China are way cheaper then 3.3 / 8MHz.

Facts that I already know:

If I follow the datasheet to the the letter, this configuration should not work. BUT... After some test, it did work.

Also, I want an answers based on *personal experience* (NOT OPINIONS) and not datasheet and specs.

---

***[EDIT]*** Including a way to use the internal clock (at 8MHz) of the ATmega328P would really help!

title: Arduino 16 MHz with only 3.3V?

Answers: 7

body:
Officially, no.  Practically, often but not always.

>If I follow the datasheet to the the letter, this configuration should not work. BUT... After some test, it did work.

The data sheet does not say that it "should not" work, it says that it is that the part is *not qualified* for operation at 16 MHz below some voltage higher than you want to use.  That does not mean that a given chip cannot work there, it only means that a chip that fails to may not be considered "bad".  Failure may be total and obvious or subtle.

In practice I have seen it work, both on small modified import boards and those with switchable power supply voltage.  But I also recall seeing it fail to work.

Two factors that can make a theoretical difference are part-to-part manufacturing variation and operating temperature.

Note that with an ISP setup you can change the fuses to run the chip on what was sold as a 5v external crystal board, to operate from the internal 8 MHz oscillator instead, *and you can do this even while leaving the crystal on the board*.  If you also change the brownout detector fuse, you can lower the voltage further, for example to operate without a regulator directly on two AA cells.  Of course that applies to the ATmega itself - any other active components on the board would have to be qualified for the intended voltage too.

body:
I've built a few 3.3v home-brew-duinos with 16Mhz crystals (because I have a bag of 50 xtals!) - they run fine in the conditions I've put them in so far (on my desk). Some of them may be closer to their margins than others, and might fail at at some otherwise in-spec temperature, for example. If these were intended to go outside (enclosed, of course), I'd have to test them against the conditions they might be subjected to. Or redesign them to keep them in spec in the first-place.

I think the only way to know is to try it on your board and see. I don't have or know of a test-suite for the chip; I've just uploaded known-working sketches to my experimental boards and had no obvious glitches. Yet.

body:
A little test, not very scientific, but shows it runs fine on 3.3V - https://www.youtube.com/watch?v=If0eOa0Uj5I.

Again, if you would like to stay withing the specification just use a "clock divider/2" and run your MCU at 8MHz if they have a 16MHz Crystal:

    clock_prescale_set(clock_div_2)

http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html

body:
According to the datasheet you need 3.78V to run at 16 MHz, and 3.3V isn't that far off. I would be surprised, for example, if it stopped working at 3.77V, because that would mean that the operating at 3.78V was marginal.

I have operated these chips out of spec, for example under voltage, or with a 24 MHz crystal. They *seem* to work. However I would guess that Atmel's position would be: *if you operate out of our specs, don't come crying to us if it is unreliable*.

A few percent out of spec will probably work - and 3.3V is 87% of 3.78V. They write those specs to allow for fluctuations in the manufacturing process, and are confident that *all* their chips would meet them. Probably a lot of chips would be over spec.

---

>  Including a way to use the internal clock (at 8MHz) of the ATmega328P would really help!

Set the fuses appropriately. See [Engbedded Atmel AVR® Fuse Calculator](http://www.engbedded.com/fusecalc)

For the Atmega328P making the low fuse be 0xE2 should do it.

---

> The reason I'm doing this is because 5V / 16MHz Pro Minis from China are way cheaper then 3.3 / 8MHz.

Be cautious that cheap clone boards may be manufactured with manufacturers' "seconds".

body:
I am running my atmega328p chip with 3.3 volts because I did not wanted to use a voltage divider when powering the NRF24L01 that is part of my circuit. Because I only have 16mhz crystals and I don't know how to lower the frequency to 8mhz I been running my project with 3.3v and it works great. I been running this code for over a year and I have had no problems.

The code works great even at 2.8v running at 16mhz.  At 2.65v it stops working.

body:
You can use the clock prescaler in conjunction with the CKDIV8 fuse to operate with an 8MHz clock but using a 16MHz crystal.

See the "CLKPR – Clock Prescale Register" details in the data sheet for details (Page 36 in my data sheet 07/2012).

Basically you set the CKDIV8 fuse so the processor runs at 2MHz after power-up. Then once up and running you set the division ratio to 2 which would give 8MHZ operation which is guaranteed at 3.3V.

body:
Atmega48/168/328's datasheet graph (under *"29.3: Speed Grades"*) presents maximum safe clock speed for given *VDD* voltage. It consists of three mathematical functions - 1 constant and 2 linear. I managed to calculate their formulas and sum them up:

[![formulas][1]][1]

where:

*x* is a *VDD* voltage [V] and *y* - max safe clock speed [MHz] you can achieve with the voltage. I've done it, because I've had a need to check, if 3.3V power supply is enought for a 12MHz crystal - and it is (around 13,3MHz max.).

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


body:
I am running a control program for an ebike on an Arduino MEGA2560 which uses this MCU: http://www.atmel.com/devices/atmega2560.aspx. Currently, the program loops every 100ms which gives me a sample rate of 10Hz for measurements and control signal. I would like at least 10 times that so 100Hz. How can I work out which specs I need based on the arduino MEGA2560 and the perf it's giving me?
Thanks!

Here is my code, it basically calculates battery capacity, range as well as controls and smooths the throttle inputs:

    #include <EEPROM.h>
    #include <memorysaver.h>
    //#include <TFT_HX8357.h> // Hardware-specific library
    #include <URTouch.h>
    #include <URTouchCD.h>
    #include <memorysaver.h>
    #include <UTFT.h>

    //TFT_HX8357 myGLCD = TFT_HX8357();       // Invoke custom library#include <TFT_HX8357.h> // Hardware-specific library
    //
    //TFT_HX8357 myGLCD = TFT_HX8357();       // Invoke custom library

    UTFT myGLCD(ILI9481,38,39,40,41);
    URTouch myTouch(6, 5, 4, 3, 2);

    int buttonst, horn=5, throttle=8, powermode=1, alarmsystem=1, xtouch, ytouch, k1=0, k2=0,modechange,ncycles, p=9, divider=12, addresstd=0;
    float pushed, pushedt, timesp, timespm1, powtimesm, factor, powtimesp, start, elapsed, powtime, powresttime, shuntvoltage, batvoltage,  internresistance=0.00112, current, power, consumah, capacstore, consumwh, consumbatper, consumbatrange, distance, distanceint, throttlein, throttleout, distancedisp, Totaldist, velocity, Totaldistcheck;
    float throttlesmooth, capaccheck, capacactual,consumahstore, kpow[3]={0,0,0}, kcur[3]={0,0,0}, ksp[3]={0,0,0}, errorpower[2], errorpoweri, errorpowerli, errorcuri, errorcurrent[2], errorpowerl[2], diff, errorspeed[2], errorisp, outspeed, outcurrentctl, outspeedctl, elapsedtot, errorsmooth[2];

    float batteryspec[6][56]={{4.2,4,3.94,3.90,3.876,3.86,3.852,3.844,3.826,3.809,3.795,3.783,3.765,3.744,3.728, 3.710,3.692,3.672,3.650,3.631,3.613,3.591,3.573,3.556,3.532,3.508,3.488,3.463,3.439,3.417,3.399,3.380,3.366,3.352,3.332,3.312,3.291,3.273,3.253,3.237,3.217,3.196,3.176,3.150,3.123,3.087,3.051,2.994,2.929,2.868,2.796,2.727,2.650,5.261,2.502},//5A discharge 18650GA SPEC
      {0.001,0.002,0.015,0.047,0.085,0.133,0.186,0.244,0.309,0.383,0.447,0.506,0.554,0.612,0.681,0.735,0.793,0.852,0.921,1.007,1.081,1.150,1.236,1.300,1.358,1.438,1.518,1.587,1.667,1.747,1.822,1.888,1.955,2.014,2.072,2.152,2.232,2.317,2.389,2.466,2.524,2.594,2.658,2.722,2.786,2.847,2.925,2.983,3.063,3.133,3.186,3.245,3.293,3.330,3.357,3.368},
      {4.20,4.02,3.980,3.945,3.927,3.914,3.904,3.890,3.874,3.860,3.843,3.821,3.797,3.776,3.756,3.734,3.713,3.695,3.675,3.652,3.634,3.614,3.593,3.569,3.543,3.522,3.5,3.480,3.459,3.441,3.419,3.398,3.378,3.360,3.339,3.321,3.301,3.278,3.254,3.230,3.199,3.164,3.128,3.085,3.037,2.990,2.937,2.878,2.837,2.795,2.746,2.693,2.648,2.598,2.549,2.496},
      {0,0.007,0.033,0.084,0.151,0.223,0.294,0.377,0.457,0.521,0.574,0.646,0.718,0.785,0.851,0.931,1.011,1.091,1.171,1.251,1.323,1.397,1.469,1.547,1.632,1.701,1.778,1.853,1.928,1.994,2.088,2.175,2.258,2.333,2.413,2.487,2.562,2.634,2.706,2.775,2.842,2.908,2.697,3.023,3.074,3.116,3.159,3.205,3.234,3.261,3.287,3.314,3.333,3.352,3.365,3.379},//3A discharge 18650GA SPEC
      {4.2,4.131,4.094,4.073,4.054,4.038,4.028,4.015,4.003,3.985,3.965,3.945,3.921,3.894,3.870,3.850,3.830,3.811,3.795,3.775,3.759,3.739,3.716,3.692,3.674,3.648,3.623,3.601,3.578,3.561,3.542,3.522,3.502,3.486,3.467,3.445,3.423,3.401,3.374,3.350,3.324,3.291,3.253,3.210,3.168,3.123,3.075,3.026,2.964,2.897,2.838,2.781,2.715,2.652,2.585,2.502},
      {0,0,0.036,0.084,0.154,0.223,0.289,0.356,0.420,0.489,0.553,0.620,0.686,0.761,0.838,0.908,0.985,1.054,1.134,1.214,1.283,1.358,1.438,1.523,1.584,1.667,1.755,1.835,1.920,2.002,2.085,2.170,2.255,2.327,2.402,2.482,2.567,2.644,2.724,2.791,2.850,2.908,2.964,3.015,3.058,3.095,3.132,3.167,3.207,3.245,3.271,3.295,3.320,3.336,3.354,3.365}}; //1A discharge 18650GA SPEC

    float cyclicspec[2][44]={{0,0.894,7.151,16.09,26.4,37.5,50.95,61.68,74.19,85.36,96.54,107.26,118.88,130.95,142.12,154.64,168.04,182.35,194.86,208.27,219.89,234.2,246.7,262.8,276.2,291.4,303.9,317.3,327.15,341.5,354,364,374.5,383.46,395.08,405.8,418.3,431.7,444,455.9,468.8,481.9,491.6,499.7},
      {3441.3,3435.7,3342.9,3292.9,3235.7,3178.6,3121.4,3078.6,3014.28,2957.1,2921.4,2892.9,2842.9,2792.9,2750,2721.4,2678.6,2642.9,2607.1,2564.3,2542.9,2507.1,2478.6,2435.7,2407.1,2378.6,2357.1,2335.7,2335.7,2335.7,2335.7,2335.7,2335.7,2321.4,2300,2278.6,2271.4,2242.9,2228.6,2214.3,2192.9,2178.6,2164.3,2157.1}};

    extern uint8_t BigFont[];
    extern uint8_t SevenSegNumFont[];

    void EEPROMWritelong(int address, long value)
          {
          //Decomposition from a long to 4 bytes by using bitshift.
          //One = Most significant -> Four = Least significant byte
          byte four = (value & 0xFF);
          byte three = ((value >> 8) & 0xFF);
          byte two = ((value >> 16) & 0xFF);
          byte one = ((value >> 24) & 0xFF);

          //Write the 4 bytes into the eeprom memory.
          EEPROM.write(address, four);
          EEPROM.write(address + 1, three);
          EEPROM.write(address + 2, two);
          EEPROM.write(address + 3, one);
          }

    float EEPROMReadlong(int address)
          {
          //Read the 4 bytes from the eeprom memory.
          long four = EEPROM.read(address);
          long three = EEPROM.read(address + 1);
          long two = EEPROM.read(address + 2);
          long one = EEPROM.read(address + 3);

          //Return the recomposed long by using bitshift.
          return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
          }

    float pidcurrent_control() {
     float dt, outcurrent=0, outpower=0;
     int i=0, descurrent, despower;
     i++;
     dt=millis()-powtime;
     powtime = millis();
     if (powermode==1) { //Furo default mode
      if (current>40) {
        descurrent=40;
        errorcurrent[1]=descurrent-current;
        if (i>=2) {
          //Integrate the error
        errorcuri+=errorcurrent[1]*dt;

        outcurrent=(kcur[0]*errorcurrent[1]+kcur[1]*errorcuri+kcur[2]*((errorcurrent[1]-errorcurrent[0])/dt));
        }
        errorcurrent[0]=errorcurrent[1];
        return outcurrent;
        }
        if ((batvoltage*current)>2000) {
         despower=2000;
          errorpower[1]=despower-batvoltage*current;
          if (i>=2) {
        //Integrate the error
        errorpoweri+=errorpower[1]*dt;
        outpower=kpow[0]*errorpower[1]+kpow[1]*errorpoweri+kpow[2]*((errorpower[1]-errorpower[0])/dt);
        }
        errorpower[0]=errorpower[1];
        return outpower;
        }
        }
      else { //Eco mode
       despower=550;
       errorpowerl[1]=despower-batvoltage*current;
          if (i>=2) {
          //Integrate the error
          errorpowerli+=errorpowerl[1]*dt;
          outpower=kpow[0]*errorpowerl[1]+kpow[1]*errorpowerli+kpow[2]*((errorpowerl[1]-errorpowerl[0])/dt);
        }
        errorpowerl[0]=errorpowerl[1];
        return outpower;
        }
        }

    void cyclescaling() {
    int j=1;
     if (ncycles<=499) {
     while ((ncycles<cyclicspec[0][j-1])||(ncycles>cyclicspec[0][j])){
               j++;
        }
        factor=(cyclicspec[1][j-1]+(ncycles-cyclicspec[0][j-1])*(cyclicspec[1][j]-cyclicspec[1][j-1])/(cyclicspec[0][j]-cyclicspec[0][j-1]))/cyclicspec[1][0];
    }
    else {
        factor=(cyclicspec[1][41]+(ncycles-cyclicspec[0][41])*(cyclicspec[1][42]-cyclicspec[1][41])/(cyclicspec[0][42]-cyclicspec[0][41]))/cyclicspec[1][0];
    }
    }

    float pidspeed_control() {
    int isp, dtsp;
    isp++;
    dtsp=millis()-powtimesp;
    powtimesp = millis();
    errorspeed[1]=46-velocity;
    if (isp>=2) {
        errorisp+=errorspeed[1]*dtsp;
        outspeed=(ksp[0]*errorspeed[1]+ksp[1]*errorisp+ksp[2]*((errorspeed[1]-errorspeed[0])/dtsp));
        }
        errorspeed[0]=errorspeed[1];
        return outspeed;
    }

    void throttlesmoothing() {
     int i=0, dtsm;
     i++;
     float currentmap=map(throttlein,0.8,3.6,0,40);
     dtsm=millis()-powtimesm;
     powtimesm = millis();
     errorsmooth[1]=currentmap-current;
          if (i>=2) {
          //Integrate the error
          throttlesmooth=kcur[0]*errorsmooth[1]+kcur[2]*((errorsmooth[1]-errorsmooth[0])/dtsm);
        }
        errorsmooth[0]=errorsmooth[1];
    }

    void SOC() {
      float currentref=current/p;
      int j=1,l=1;
      float stateofc1=0, stateofc2=0;

      if (currentref<=1){
        while (((batvoltage/14)>batteryspec[0][j-1])||((batvoltage/14)<batteryspec[0][j])){
               j++;
        }
        capacactual=(batteryspec[1][55]-(batteryspec[1][j-1]+(batvoltage/14-batteryspec[0][j-1])*(batteryspec[1][j]-batteryspec[1][j-1])/(batteryspec[0][j]-batteryspec[0][j-1])))*p;

      }

     if ((currentref>1)&&(currentref<=3)){
        while (((batvoltage/14)>batteryspec[0][j-1])||((batvoltage/14)<batteryspec[0][j])){
               j++;
        }
        stateofc1=(batteryspec[1][55]-(batteryspec[1][j-1]+(batvoltage/14-batteryspec[0][j-1])*(batteryspec[1][j]-batteryspec[1][j-1])/(batteryspec[0][j]-batteryspec[0][j-1])))*p;

         while (((batvoltage/14)>batteryspec[2][l-1])||((batvoltage/14)<batteryspec[2][l])){
               l++;
        }
        stateofc2=(batteryspec[3][55]-(batteryspec[3][l-1]+(batvoltage/14-batteryspec[2][l-1])*(batteryspec[3][l]-batteryspec[3][l-1])/(batteryspec[2][l]-batteryspec[2][l-1])))*p;
        capacactual=stateofc1+(currentref-1)*(stateofc2-stateofc1)/(3-1);
      }

       if ((currentref>3)&&(currentref<=5)){
        while (((batvoltage/14)>batteryspec[2][j-1])||((batvoltage/14)<batteryspec[2][j])){
               j++;
        }
    //    stateofc1=(batteryspec[3][55]-(batteryspec[3][j-1]+(batvoltage/14-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p;

         while (((batvoltage/14)>batteryspec[2][l-1])||((batvoltage/14)<batteryspec[2][l])){
               l++;
        }
    //    stateofc2=(batteryspec[3][55]-(batteryspec[3][l-1]+(batvoltage/14-batteryspec[2][l-1])*(batteryspec[3][l]-batteryspec[3][l-1])/(batteryspec[2][l]-batteryspec[2][l-1])))*p;
        capacactual=(batteryspec[3][55]-(batteryspec[3][j-1]+(batvoltage/14-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p+(currentref-1)*((batteryspec[5][55]-(batteryspec[5][l-1]+(batvoltage/14-batteryspec[4][l-1])*(batteryspec[5][l]-batteryspec[5][l-1])/(batteryspec[4][l]-batteryspec[4][l-1])))*p-(batteryspec[3][55]-(batteryspec[3][j-1]+(batvoltage/14-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p)/(5-3);

      }

    if (currentref>5) {
       while (((batvoltage/14)>batteryspec[4][j-1])||((batvoltage/14)<batteryspec[4][j])){
               j++;
        }
        capacactual=(batteryspec[5][55]-(batteryspec[5][j-1]+(batvoltage/14-batteryspec[4][j-1])*(batteryspec[5][j]-batteryspec[5][j-1])/(batteryspec[4][j]-batteryspec[4][j-1])))*p;
    }

    }

    void autonomy() {

      if (modechange==1) {
       consumah=0;
      }

        power=batvoltage*current;
        SOC();
        if (capacactual!=capaccheck) {
          capaccheck=(capacactual+capaccheck)/2;
        }

      if (abs(capacactual-capacstore)>=0.1){
         EEPROMWritelong(8,roundf(capacactual*1000));
         capacstore=capacactual;
      }

      consumah += current*elapsed/1000/3600;
      capaccheck -= current*elapsed/1000/3600;
      consumwh += current*elapsed/1000/3600*batvoltage;
      elapsedtot += elapsed;
      consumbatper = (capaccheck)/(batteryspec[1][55]*p)*100;
      if (distance==0) {
        switch (powermode) {
          case 1: consumbatrange=45*batvoltage*capaccheck/980;
          break;
          case 2: consumbatrange=35*batvoltage*capaccheck/550;
          break;
        }

      } else {
      consumbatrange = distance/consumah*(capaccheck);
      }
      myGLCD.printNumF(consumbatrange, 2, 350,275);
      myGLCD.printNumF(power, 2, 350,205);
      myGLCD.printNumF(current, 1, 30,50);
      myGLCD.printNumF(ncycles, 1, 30,50+16*2);
      myGLCD.printNumF(consumbatper,1,350,50);
      myGLCD.printNumF(batvoltage,1,350,50+16*2);

      return 0;

    }

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      start=millis();
      pinMode(43, OUTPUT);//Speedo power
      pinMode(46, INPUT);//Speedometer
      pinMode(A2, INPUT);//Throttle in
      pinMode(A7, INPUT);//Battery voltage
      pinMode(A4, INPUT);//Shunt
      pinMode(throttle, OUTPUT);
      pinMode(11, OUTPUT);
      pinMode(10, OUTPUT);
      pinMode(47, INPUT);

      analogWrite(10,255);
      analogWrite(11,255);

      myGLCD.InitLCD(LANDSCAPE);
      myTouch.InitTouch(LANDSCAPE);
      myGLCD.fillScr(0,0,0);
      myGLCD.setColor(VGA_WHITE);
      myGLCD.setBackColor(0,0,0);
      myGLCD.setFont(BigFont);
      myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
      myGLCD.print("WELCOME",(480-16*7)/2,(320-16)/2);
      myGLCD.setDisplayPage(0);
      delay(2000);
      myGLCD.clrScr();
      myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
      myGLCD.fillRoundRect((480-3*16-8)/2,320-16*2-4,(480-3*16-8)/2+3*16+6,228);
      myGLCD.print("ECO", (480-3*16)/2, 320-16*5);
    //  EEPROMWritelong(4,1);
      ncycles=EEPROMReadlong(4);
      cyclescaling();

      for (int m=1; m<=5;m+=2) {
      for (int n=0; n<=55;n++) {
        batteryspec[m][n]*=factor;
        }
      }

      current=analogRead(A4);
      current=current/internresistance*5/1023/75;;

      batvoltage=analogRead(A7);
      batvoltage=batvoltage*5*divider/1023;

      SOC();
      capaccheck=capacactual;
      capacstore=EEPROMReadlong(8)/1000;

      if (capacactual>capacstore) {
      ncycles++;
      EEPROMWritelong(4,ncycles);
      EEPROMWritelong(8,roundf(capacactual*1000));
      }

      if (capacactual<0.5) {
        powermode=2;
        myGLCD.fillRoundRect((480-4*16-8)/2,320-16*2-4,(480-4*16-8)/2+4*16+6,228);
        myGLCD.print("FURO", (480-4*16)/2, 320-16*5);
      }//3.21V per cell
      EEPROMReadlong(addresstd);
      Totaldist=EEPROMReadlong(addresstd);
      Totaldistcheck=Totaldist;
      digitalWrite(43,HIGH);
    }

    void loop() {

       throttlein=analogRead(A2);
       throttlein=throttlein*5/1023;
       throttlesmoothing();
       throttleout=round((0.4+throttlein)*255/5);
       analogWrite(8,throttleout);

       modechange=0;
        if (digitalRead(47)==LOW)
        {
          if (buttonst==1) {
          pushed = millis();
          }
          buttonst=0;

          if ((millis()-pushed)>=2000)
          {
           distancedisp=0;
          }
          }

         if (digitalRead(47)==HIGH) {
          if (buttonst==0) {
            modechange=1;
            pushedt=millis()-pushed;
            if (pushedt<1900){
           if (powermode==1)
          { powermode=2;
           myGLCD.clrScr();
           myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
           myGLCD.fillRoundRect((480-4*16-8)/2,320-16*2-4,(480-4*16-8)/2+4*16+6,228);
           myGLCD.print("FURO", (480-4*16)/2, 320-16*5);
          }
          else
          {
            powermode=1;
            myGLCD.clrScr();
            myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
            myGLCD.fillRoundRect((480-3*16-8)/2,320-16*2-4,(480-3*16-8)/2+3*16+6,228);
            myGLCD.print("ECO", (480-3*16)/2, 320-16*5);
          }
          }
          }
          buttonst=1;
         }

    batvoltage=analogRead(A7);
    batvoltage=batvoltage*5*divider/1023;
    current=analogRead(A4);
    current=current/internresistance*5/1023/75;
    elapsed = millis() - start;
    start = millis();

    if (modechange==1) {
       distance=0;
    }
    distanceint = (velocity/3.6*elapsed*0.001)/1000;
    distance += distanceint;
    distancedisp += distanceint;
    Totaldist += distanceint;

    if (abs(Totaldist-Totaldistcheck)>=0.1) { //later do it upon switch off
      EEPROMWritelong(addresstd,round(Totaldist));
      Totaldistcheck=Totaldist;
    }

    autonomy();

    if (velocity>45) {
    outspeedctl=pidspeed_control();
    outcurrentctl=pidcurrent_control();
    float throttleout1=min(outspeedctl,outcurrentctl);
    throttleout=min(throttleout1,throttlesmooth);
    analogWrite(throttle, map(throttleout, 0,5,0,255));
    } else{
    outcurrentctl=5;
    outcurrentctl=pidcurrent_control();
    throttleout=min(throttlesmooth,outcurrentctl);
    analogWrite(throttle, map(throttleout, 0,5,0,255));
    }

    myGLCD.setFont(SevenSegNumFont);
    myGLCD.printNumI(velocity, (480-32*3)/2, (320-50)/2);
    myGLCD.setFont(BigFont);
    myGLCD.printNumF(distancedisp, 1, 30,175);
    myGLCD.printNumI(Totaldist, 30,175+2*16);

    }

title: Extrapolate require MCU from Arduino MEGA2560 performance

Answers: 1

body:
There are three things that i can see that are holding your code back.

AnalogRead in Arduino is very slow. The ADC in the chip is not the greatest but also the AnalogRead function will hold you there until a full read and conversion are complete. It may be possible to trigger a sample and conversion and read the answer later. Look for a chip that can sample multiple ADC channels without processor intervention. A digital signal processor (DSP) such as a dspic33epxxxxxx could be of great service. They have very high analog sampling capability.

Also EEPROM writes are very slow. Finding a way around them or using external memory could help increase your speed. The EEPROM write has to hold your code until the write is complete. This is very similar the the ADC.

Float calculations inside a processor that has no float math core is like shooting yourself in the foot, all you can do from there is limp. Find the minimum number of decimal places that you can live with and push them into the integer world. For example 12.7325 X 10000, could instead be 127325. Then scale all your other calculation with that scale factor in mind. The math is more tricky but 10 to 15 cycles to multiply an integer is better then 200 to over a 1000 cycles to multiply a float. By properly including some other scale factor the ADC reading can be used directly without a conversion.


body:
I'd like to 'clean up' some code that involves several `pinMode()` and `digitalWrite()` lines by using a single line of an array. I'm very new to both arrays so I'm a bit confused. The following examples are sections from code that controls a 4 digit, 7 segment LED.

    // Define display pins
    // Digit pins (common cathode)
    int digit1 = 13; //Display pin 1
    int digit2 = 12; //Display pin 2
    int digit3 = 11; //Display pin 6
    int digit4 = 10; //Display pin 8
    // Segment pins
    int segA = 2; //Display pin 14
    int segB = 3; //Display pin 16
    int segC = 4; //Display pin 13
    int segD = 5; //Display pin 3
    int segE = 6; //Display pin 5
    int segF = 7; //Display pin 11
    int segG = 8; //Display pin 15

    void setup() {
      pinMode(segA, OUTPUT);
      pinMode(segB, OUTPUT);
      pinMode(segC, OUTPUT);
      pinMode(segD, OUTPUT);
      pinMode(segE, OUTPUT);
      pinMode(segF, OUTPUT);
      pinMode(segG, OUTPUT);

      pinMode(digit1, OUTPUT);
      pinMode(digit2, OUTPUT);
      pinMode(digit3, OUTPUT);
      pinMode(digit4, OUTPUT);
    }

    #define SEGMENT_ON  LOW
    #define SEGMENT_OFF HIGH

      switch (numberToDisplay){

      case 0:
        digitalWrite(segA, SEGMENT_ON);
        digitalWrite(segB, SEGMENT_ON);
        digitalWrite(segC, SEGMENT_ON);
        digitalWrite(segD, SEGMENT_ON);
        digitalWrite(segE, SEGMENT_ON);
        digitalWrite(segF, SEGMENT_ON);
        digitalWrite(segG, SEGMENT_OFF);
        break;

Defining pins:

I'm pretty sure the code below is the correct way to store the pins as an array (but please correct me  if I'm wrong).

    digitPins[] = {13 12 11 10};
    segPins[] = {2 3 4 5 6 7 8};

**`pinMode():`**

I understand I could use a for loop to set the pin modes but is there an even simpler way? Would something like this work?

    pinMode(digitPins[], OUTPUT);
    pinMode(segPins[], OUTPUT);

**`digitalWrite():`**

I could access the appropriate pin from the array to use in `digitalWrite()` like the code below but that would result in the same number of lines of code (and be even more confusing). Is there another option?

    digitalWrite(segPins[1], HIGH);

title: Replacing several pinMode() and digitalWrite() pins with an array

Answers: 3

body:
***[ADDITIONNAL CODE and EXPLANATION OF THE CODE]***

This is the function that is used in the link posted in the comments:

    void number(int num)                        //num is the number to display
    {
      for(int i=0; i<7; i++)                    //going through the 7-segments (7 leds)
      {
        digitalWrite(segment[i], nums[num][i]); //tell the arduino to turn on or off which led
      }
    }

It is great because you can use it by calling:

    number(/*the number you want to display*/);

Using a for loop will avoid copying and pasting a buch of things. It also permits you do save a lot of memory.

Then, to display a small 0-9 timer, you can do this:

    for(int i=0; i<10; i++)
    {
      number(i);            //display the number
      delay(1000);          //wait 1sec
    }

---

***[ORIGINAL ANWSER]***

Use an array and a for loop.

    int segments = {2,3,4,5,6,7,8}; //declaring the pins

    void setup() {
      for(int i=0;i<8;i++)
      {
        pinMode(segments[i], OUTPUT); //declaring them as outputs
      }
    }

It's very useful. Do the same for the digits too.

This method works in many cases:

- many sensors, switches
- many outputs such as leds, relays, transistors

body:
> the correct way to store the pins as an array

Your array initializers are almost right; you just need to separate the values with commas:

    digitPins[] = {13, 12, 11, 10};
    segPins[] = {2, 3, 4, 5, 6, 7, 8};

You will need to call pinMode() in a loop; it doesn't accept arrays as arguments.

> How about for digitalWrite() where its a mix of HIGH and LOW?

There are (at least) two ways: Make arrays of HIGH and LOW values, matching the digitPins[] and segPins[] arrays one-for-one, respectively. Or for easier maintenance, declare a data structure (`struct`) of a pin # and a value; make an array of those. It's a bit more complex but also more useful. So, for example:

    typedef struct {
     uint8_t pinNum;
     bool pinVal;
    } pinInit_t;

    pinInit_t digitPins[] {
     {13, HIGH},
     {12, LOW},
     {11, LOW},
     {10, HIGH}
    };

    void setup() {
      // put your setup code here, to run once:
    }

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

`struct` is short for "data structure"; it lets you combine data of different types into a single named and addressable unit. `typedef` declares a new data type, and says "Don't allocate any memory just now; this (pinInit) is just a description. I'll use it later on." It makes pinInit a named data type, usable wherever you can use a native data type AND a multi-valued data type (such as an array) is permissible.

Thus, we can make an array of `pinInit`s (pin-# / boolean-value pairs) just by using the name of the new type.

Then your initializing code might look like:

    uint8_t i;
    for( i = 0; i < sizeof(digitPins)/sizeof(pinInit_t); ++i ){
       pinMode(digitPins[i].pinNum, OUTPUT);
       digitalWrite(digitPins[i].pinNum, digitPins[i].pinVal);
    }

The expression `sizeof(digitPins)/sizeof(pinInit)` evaluates to the number of initializers (# of bytes in the array / # of bytes in one array member).

The expression `digitPins[i].pinNum` means: "in the pinInit array digitPins, get the i-th element..." (remember, this is a pair of values), "... and take value of the member "pinNum". A little more complex, the first time we think about it, but look at how easily the array reads. And a hint about reading that expression: I read it backwards: "the pinNum member of the i-th element of the digitPins array."

Tomorrow, or next month, when we need another pin, no need to update 2 arrays (remembering of course, to keep them in sequence with each other!); just add another 2-valued element to the one digitPins[] array.

body:
# Custom method usage #
Used reference: https://stackoverflow.com/a/33235154/5500092

You can use a custom method like this:

    template<size_t size>
    void pinMode(const uint8_t (&pin)[size], uint8_t mode) {
     for (size_t i = 0; i < size; ++i) {
      pinMode(pin[i], mode);
     }
    }

    template<size_t size>
    void digitalWrite(const uint8_t (&pin)[size], uint8_t val) {
     for (size_t i = 0; i < size; ++i) {
      digitalWrite(pin[i], val);
     }
    }

Then you define an array with the pins:

    uint8_t displayPins[4] = {13, 12, 11, 10};
    uint8_t segmentPins[7] = {2, 3, 4, 5, 6, 7, 8};

And finally in your setup use:

    void setup() {
     pinMode(displayPins, OUTPUT);
     pinMode(segmentPins, OUTPUT);
    }

    void loop() {
        // Your logic with digitalWrite.
    }

----
# Your logic #

PS: For your logic, you can even use:

    template<size_t size>
    void digitalWrite(const uint8_t (&pin)[size], const uint8_t (&val)[size]) {
     for (size_t i = 0; i < size; ++i) {
      digitalWrite(pin[i], val[i]);
     }
    }

And define for each segment number a custom value array.

    uint8_t zero[7] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW};
    ...

Or even:

    uint8_t segment[][7] = {{HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW }, // 0
                            {____, ____, ____, ____, ____, ____, ____}, // 1
                            {____, ____, ____, ____, ____, ____, ____}, // 2
                            ...
                            {____, ____, ____, ____, ____, ____, ____}}; // F

And use:

    digitalWrite(segmentPins, segment[5]); // print 5


body:
I just started with my Arduino UNO so please pardon my ignorance with SoftwareSerial but I need help. My goal is to make a system of 4 SoftwareSerial ports. Port1 will receive a burst of 5-10 characters and I will then transmit on eventually Port2,3 & 4. Maybe all or just 1 depending on an operator setting. I made the simplest system to try it where I receive on port1 and display on Serial Monitor. All works well until I do a begin to the second port which is commented out in the listing. When it is not commented out it looks like Port1 receives nothing, no display Port1 never says "available" therefore nothing. Any ideas would be most appreciated.

    #include <SoftwareSerial.h>
    SoftwareSerial RotorPort1 (8, 9); //RX, TX
    SoftwareSerial RotorPort2 (10, 11);

    int RotorPortSpeed = 9600;

    void setup() {
      Serial.begin(9600);
     RotorPort1.begin(RotorPortSpeed);
      //  RotorPort2.begin(RotorPortSpeed);
      delay(200);
     }

    void loop() {
     if (RotorPort1.available()) {
        byte incomingByte = RotorPort1.read();
        Serial.print ("data= ");
        Serial.print(incomingByte);
        Serial.print("  ");
        Serial.print(char (incomingByte));
        Serial.println();
        delay (300);

      }
    }

title: Help to get Arduino UNO with 4 SoftwareSerial transmit only ports

Answers: 2

body:
As Chris Stratton suggests, multiple instances of SoftwareSerial may cause issues, particularly with pin-change interrupts.

I adapted SoftwareSerial a while back to have a "send only" version. This can be downloaded from [here](http://www.gammon.com.au/Arduino/SendOnlySoftwareSerial.zip) - 6 KB.

One normal SoftwareSerial and 3 instances of the "send only" may possibly help. I haven't tested it.

---

Chris's suggestion to modify SoftwareSerial to allow pin number changes on-the-fly may be even better. SoftwareSerial can only write to one pin at a time as it blocks, and thus having 4 instances of it doesn't really achieve anything.

---

Another possible approach would be to use a multiplexer chip. I have [a page about that](http://www.gammon.com.au/forum/?id=11976). You could have a single SoftwareSerial instance, and then use the multiplexer to forward its data to one of (up to 8) pins.

[![Multiplexer][1]][1]

You would need pull-up resistors to keep the other pins high (idle) when not in use at a particular moment.

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

body:
IT WORKS!  The solution was to do RotorPort1.listening() right after starting both ports.  Apparently when there are multiple receivers you have to declare which one is the listener but can be changed on the fly.  Nothing in the documentation really said that.
I was almost ready to do the hardware mux since I have been a hardware guy for 30 years and really wanted to do it in software.
You have all been a ton of help.  Thank you. The DJ


body:
In Arduino code, I'm calling the `getTextBounds()` and `print()` API methods on my TFT handler object which accepts `char*` parameters and I have two integers holding a specific time's hour and minute part, for example:

    int _hour = 7;
    int _minute = 30;

I need to construct a `char*` variable that holds this string: `07:30`.
What is the simplest way to do that?

I tried this:

    char* timestr = (_hour < 10 ? '0' : '') + _hour + ':' + (_minute < 10 ? '0' : '') + _minute;

But it gives me two kind of errors:

    error: empty character constant
    error: invalid conversion from 'int' to 'char*' [-fpermissive]

title: Format hour and minute integers to HH:MM format (char*)

Answers: 2

body:
You don't want a `char *`, you want a character array, i.e. you have to
allocate the memory for the string, not only for a pointer. That being
said, you can build the string one character at a time like this:

<!-- language-all: lang-c -->

    char timestr[6];
    timestr[0] = '0' + _hour / 10;
    timestr[1] = '0' + _hour % 10;
    timestr[2] = ':';
    timestr[3] = '0' + _minute / 10;
    timestr[4] = '0' + _minute % 10;
    timestr[5] = '\0';

Then you can use `timestr` just as you would use a `char*`.

**Edit 1**: If you are not too short on RAM, you could allocate the string
statically, and have the C runtime initialize the characters `':'` and
`'\0'` at program startup. Then you just have to set the four remaining
chars on each conversion:

    static char timestr[] = "--:--";  // initialized only once, with template
    timestr[0] = '0' + _hour / 10;
    timestr[1] = '0' + _hour % 10;
    timestr[3] = '0' + _minute / 10;
    timestr[4] = '0' + _minute % 10;

**Edit 2**: Maybe the “simplest”, in the sense “closest to what you had
in mind”, would be to use a `String` object:

    String timestr = String() + (_hour < 10 ? "0" : "") + _hour
        + ':' + (_minute < 10 ? "0" : "") + _minute;

You could `print()` that String directly, or retrieve the internal
`char*` with the `c_str()` method.

I added this method only for completeness. Although simple in the source
code, it would not be my first choice: it uses more memory, it is more
CPU-intensive and – what worries me most – it uses heap allocation,
which carries the risk of memory fragmentation.

body:
What about using `stdio.h`? I know, it eats up some flash space, but:

    #include <stdio.h>

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

    void loop() {
      int _hour = 3;
      int _minute = 9;
      char buff[14]; // in worst case 6digigts per integer, separator and string terminating char

      sprintf_P(buff, PSTR("d:d"), _hour, _minute); // format string resides in flash (it needs special version of sprintf.
      // sprintf(buff, "d:d", _hour, _minute); // usual variant, but format is stored in RAM (and Flash too)

      Serial.println(buff);
      delay(5000);
    }


body:
I am using I2C to successfully request critical data from a Slave device (I **have** to use requestFrom() in the Master) but if, for some reason, the power disconnects from the Slave device then the Master freezes altogether. I didn't realise I2C was so problematic in this regard and I have been a number of weeks trying all types of alternative setups to try and avoid this situation. I can't seem to find a way for example, to simply check if a Wire() connection exists before requesting data and freezing everything. Both devices are Arduino Uno r3.
Any ideas I may not have tried yet? Any way to send a single value to the Master and update it every 30 secs would do. Actually the data comes from a capacitive sensor, so would it be possible to just have both arduinos read from the same sensor?

In response to Nick Gammons suggestions (below):
I have edited the examples you gave to try and fit in with what I am trying to achieve. I would like to do the following. Catch a situation where the Master (Arduino Yun Shield) cannot communicate with the Slave ( Arduino r3 - with sensor) due to its power supply and/or sensor reading failing. In other words, an Arduino monitoring another Arduino. Here is my edited versions, however I am still not able to catch the "else" condition of the Slave being unreachable:

SLAVE

    #include <Wire.h>

    const byte MY_ADDRESS = 42;

    // various commands we might get

    enum {
        CMD_ID = 1,
        CMD_READ_A0  = 2
        };

    char command;

    void setup()
      {
      command = 0;
      pinMode (A0, INPUT);

      Wire.begin (MY_ADDRESS);
      Wire.onReceive (receiveEvent);  // interrupt handler for incoming  messages
      Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

      }  // end of setup

    void loop()
      {
      // all done by interrupts
      }  // end of loop

    void receiveEvent (int howMany)
      {
      command = Wire.read ();  // remember command for when we get request
      } // end of receiveEvent

    void sendSensor (const byte which)
      {
      //int val = analogRead (which);
      int val = 125;//test only
      byte buf [2];
        buf [0] = val >> 8;
        buf [1] = val & 0xFF;
        Wire.write (buf, 2);
      }

    void requestEvent ()
      {
      switch (command)
         {
         case CMD_ID:      Wire.write (0x55); break;   // send our ID
         case CMD_READ_A0: sendSensor (A0); break;  // send A0 value
         }
      }

MASTER

    #include <Process.h>
    #include <I2C.h>
    #include <Bridge.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C  lcd(0x27, 16, 2);

    const int SLAVE_ADDRESS = 42;

    // various commands we might send
    enum {
      CMD_ID = 1,
      CMD_READ_A0  = 2,
    };

    void setup ()
    {
      Bridge.begin();
      Console.begin();
      //while (!Console);
      I2c.begin ();
      I2c.timeOut(100);  // milliseconds

      lcd.init();
      lcd.backlight();
    }

    void loop()
    {
      int value = getA0();
      Console.print("A0 value:");
      Console.println(value);
      lcd.setCursor(0, 0);
      lcd.print("A0 value:");
      lcd.print(value);//displays first '0' reading then freezes code
      delay (5000);
    }

    int getA0() {
      if (I2c.write (SLAVE_ADDRESS, CMD_READ_A0) == 0) {
        byte buf [2];
        int val;
        if (I2c.read (SLAVE_ADDRESS, sizeof buf, buf) == 0)
       {
          val = buf [0] << 8 | buf [1];
          return val;
        }
        else {
          return 0;
        }
      }
      else {
        return 0;
      }
      delay(500);
    }

title: I2C connection freezes Master if Slave disconnects

Answers: 4

body:
There is code inside the standard library that loops waiting for certain interrupts to complete transmission. If the transmission fails in the middle it can hang.

See [my page about I2C](http://www.gammon.com.au/i2c). On that page I mention that there is [an alternative library](https://github.com/DSSCircuits/I2C-Master-Library). That is written a bit differently so it times out if the transmission doesn't complete in time. An alternative download to the library is [here - I2C_Rev5.zip - 6.6 KB](http://gammon.com.au/Arduino/I2C_Rev5.zip).

---

As hinted by KIIV in a comment, maybe you don't have pull-up resistors. Make sure that you have pull-up resistors from both SDA and SCL to the +5V line. A reasonable value would be 4.7k (each).

---

## Example code

> would like a few more examples to show a similar setup to replace my current requestFrom

Borrowed from [my page about I2C](http://www.gammon.com.au/i2c) I am using the same slave code as on that page.

### Slave

<!-- language: lang-c++ -->

    #include <Wire.h>

    const byte MY_ADDRESS = 42;

    // various commands we might get

    enum {
        CMD_ID = 1,
        CMD_READ_A0  = 2,
        CMD_READ_D8 = 3
        };

    char command;

    void setup()
      {
      command = 0;

      pinMode (8, INPUT_PULLUP);
      pinMode (A0, INPUT);

      Wire.begin (MY_ADDRESS);
      Wire.onReceive (receiveEvent);  // interrupt handler for incoming messages
      Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

      }  // end of setup

    void loop()
      {
      // all done by interrupts
      }  // end of loop

    void receiveEvent (int howMany)
      {
      command = Wire.read ();  // remember command for when we get request
      } // end of receiveEvent

    void sendSensor (const byte which)
      {
      int val = analogRead (which);
      byte buf [2];

        buf [0] = val >> 8;
        buf [1] = val & 0xFF;
        Wire.write (buf, 2);
      }  // end of sendSensor

    void requestEvent ()
      {
      switch (command)
         {
         case CMD_ID:      Wire.write (0x55); break;   // send our ID
         case CMD_READ_A0: sendSensor (A0); break;  // send A0 value
         case CMD_READ_D8: Wire.write (digitalRead (8)); break;   // send D8 value

         }  // end of switch

      }  // end of requestEvent

The above code responds to requests to send one of:

* Its ID (0x55)
* An analog reading (A0)
* A digital reading (D8)

---

### Master using Wire library

The master from my page was this:

    #include <Wire.h>

    const int SLAVE_ADDRESS = 42;

    // various commands we might send
    enum {
        CMD_ID = 1,
        CMD_READ_A0  = 2,
        CMD_READ_D8 = 3
        };

    void sendCommand (const byte cmd, const int responseSize)
      {
      Wire.beginTransmission (SLAVE_ADDRESS);
      Wire.write (cmd);
      Wire.endTransmission ();

      Wire.requestFrom (SLAVE_ADDRESS, responseSize);
      }  // end of sendCommand

    void setup ()
      {
      Wire.begin ();
      Serial.begin (115200);  // start serial for output

      sendCommand (CMD_ID, 1);

      if (Wire.available ())
        {
        Serial.print ("Slave is ID: ");
        Serial.println (Wire.read (), DEC);
        }
      else
        Serial.println ("No response to ID request");

      }  // end of setup

    void loop()
      {
      int val;

      sendCommand (CMD_READ_A0, 2);
      val = Wire.read ();
      val <<= 8;
      val |= Wire.read ();
      Serial.print ("Value of A0: ");
      Serial.println (val, DEC);

      sendCommand (CMD_READ_D8, 1);
      val = Wire.read ();
      Serial.print ("Value of D8: ");
      Serial.println (val, DEC);

      delay (500);
      }  // end of loop

---

### Master using I2C library

The `beginTransmission()` ... `write()` ... `endTransmission()` have been replaced by simply `write()` and the `requestFrom()` by `read()` like this:

    #include <I2C.h>

    const int SLAVE_ADDRESS = 42;

    // various commands we might send
    enum {
        CMD_ID = 1,
        CMD_READ_A0  = 2,
        CMD_READ_D8 = 3
        };

    void setup ()
      {
      I2c.begin ();
      I2c.timeOut(100);  // milliseconds
      Serial.begin (115200);  // start serial for output

      I2c.write (SLAVE_ADDRESS, CMD_ID);
      byte id;

      if (I2c.read (SLAVE_ADDRESS, sizeof id, &id) == 0)
        {
        Serial.print ("Slave is ID: ");
        Serial.println (id, DEC);
        }
      else
        Serial.println ("No response to ID request");

      }  // end of setup

    void loop()
      {

      I2c.write (SLAVE_ADDRESS, CMD_READ_A0);

      byte buf [2];
      int val;
      if (I2c.read (SLAVE_ADDRESS, sizeof buf, buf) == 0)
        {
        val = buf [0] << 8 | buf [1];
        Serial.print ("Value of A0: ");
        Serial.println (val, DEC);
        }
      else
        Serial.println ("No response to CMD_READ_A0 request");

      I2c.write (SLAVE_ADDRESS, CMD_READ_D8);
      uint8_t digitalVal;
      if (I2c.read (SLAVE_ADDRESS, sizeof digitalVal, &digitalVal) == 0)
        {
        Serial.print ("Value of D8: ");
        Serial.println (digitalVal, DEC);
        }
      else
        Serial.println ("No response to CMD_READ_D8 request");

      delay (500);
      }  // end of loop

body:
Had this same issue when using two Megas communicating over I2C, along with other items running on the I2C bus. I needed the system to continue running if one Mega went down due to loss of power. The other Mega should detect it and execute some abort commands.

Initially I wired the Megas up on the same I2C bus, just as I would any other device. When I unplugged one Mega, the other would freeze the next time it tried to address another device on the bus.

The solution was to use a hot-swappable I2C buffer. I used this one, and everything worked immediately without issue after wiring it up:
http://www.mouser.com/search/ProductDetail.aspx?r=595-TCA4311ADR

To integrate the SOIC-8 package onto a standard DIP breadboard for Arduinos, I used an adapter from Adafruit.

body:
Regarding the TI I2C hot swappable buffer:

Apparently there is a similar one from Analog Devices, but I have not tested it:
http://www.mouser.com/search/ProductDetail.aspx?r=584-ADUM1250SRZ

To integrate the SOIC-8 package onto a standard DIP breadboard for Arduinos, I used this adapter from Adafruit:
https://www.adafruit.com/product/1212

Sorry for another post - limit of 2 hyperlinks per post due to lack of reputation :-)

Chris

body:
I ran into almost the same problem in an educational context. If the I2C bus has a line stuck low, the program hangs in the wire library. In my application everything is soldered together, but not always properly, so I can get by with a single test at startup. Before invoking Wire.begin. For the OP's issue, they will want to use this every time they restart communication after an idle period.

This is part of a device's self test on power up. When one thing is assembled wrong, frequently many things are wrong, so we want to continue on and test everything else. Then the user can fix all of the issues at once. Or perhaps they haven't even built the I2C part of the circuit yet, and they want to test other hardware. In any case, hanging is not an informative way of reporting an error.

    // Written by Paul Haas for public use. This is public domain code.
    // But please don't sue me if it doesn't work.
    bool Would_I2C_Hang(int SDAPin, int SCLPin) {
      bool wouldHang = false;
      pinMode(SDAPin,INPUT);
      pinMode(SCLPin,INPUT);
      if ( digitalRead(SDAPin) != 1 ) {
     Serial.println("SDA pin is low");
     wouldHang = true;
      }
      if ( digitalRead(SCLPin) != 1 ) {
     Serial.println("SCL pin is low");
     wouldHang = true;
      }
      return wouldHang;
    }

    void setup() {
      Serial.begin(115200);
      for(int i=5;i>0;i--) {
     Serial.print(i);
     delay(1000); // I sometimes need a few seconds to restart the serial console.
      }
      Serial.println();
      if ( Would_I2C_Hang(20, 21) ) { // Adafruit Feather M0 sda and sdl arduino pins.
     Serial.println("The I2C bus will hang if we try to use it. Disabling it.");
      } else {
     Serial.println("Mark the I2C devices as ready to be tested.");
      }
    }
    void loop() {
      // put your main code here, to run repeatedly:
    }


body:
I am trying to create a simple piano playback using a flex sensor, a proximity sensor and a piezo buzzer.

I want to have it so that when the flex sensor is triggered, a sound is played on the piezo buzzer. The tone it makes is dependent on the values received from the proximity sensor.

Here is my code:

    int psrAnalogPin = 6;
    int fsrAnalogPin = 10;
    int speaker = 9;
    int fsrReading;
    int psrReading;

    void setup(void) {
      Serial.begin(9600);
      // We'll send debugging information via the Serial monitor
      pinMode(speaker, OUTPUT);
    }

    void loop(void) {
      psrReading = analogRead(6);
      delay(10);
      psrReading = analogRead(6);
      delay(10);
      Serial.print("\n psr reading = ");
      Serial.println(psrReading);
      fsrReading = analogRead(10);
      delay(10);
      fsrReading = analogRead(10);
      delay(10);
      Serial.print("\n fsr reading : ");
      Serial.println(fsrReading);
      if(fsrReading < 980 && psrReading > 599){
        tone(9, 400, 1000);
      } else if (fsrReading < 980 && psrReading > 500){
        tone(9, 500, 1000);
      } else if (fsrReading < 980 && psrReading < 392){
        tone(9, 600, 1000);
      }
    }

When I look at the serial monitor's output, the values output seem to be only reading from my flex sensor(fsrReading) and not my proximity sensor. If I only read the proximity sensor's value it works, but not both at the same time.

How can I get it so that it reads both values instead of just one?

title: How to analogRead() 2 separate pins simultanously?

Answers: 2

body:
This is not a full code but more of an explanation of the logic of your program.

>when the flex sensor is triggered, a sound is played on the piezzo buzzer. The tone it makes is dependent the values received from the proximity sensor.

Follow this logic and try to code it:

1- read the flex sensor values

    int val = analogRead(flexPin);

2- if it is triggered, THEN read the proximity sensor.

    if(val > minimum) {
      int distance = analogRead(proximityPin); //this line depends on which proximity sensor you are using

3- play the sound accordingly to the proximity sensor (still in the if loop).

    analogWrite(distance);

This logic should work fine. If you could include more info like board, flex sensor and proximity sensor, that could help.

body:
You can try using Interrupts instead of polling the sensor values, as interrupt will only be activated during rising-edge or falling edge. More info on interrupts:

 - http://playground.arduino.cc/Code/Interrupts
 - https://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/


body:
I'm new to the arduino board and my teacher gave us a project with little to no teaching about the language the board uses, or how to effectively program with it.
I'm trying to read temperature from a DHT11 and display it on two separate 7-segments displays. I've been trying to do this by editing a code he provided us that makes one display count from 0 to 9. I've been to hook up and read the DHT11 and split the temperature into two variables. But I have no idea how to make the variables display on the seven segment displays. My code is.

    //DHT11 set up
    #include <dht11.h>
    dht11 DHT11;
    void setup()
    {
       DHT11.attach(4);
       for (int i = 0; i < 4; ++i)
        pinMode(i, OUTPUT);
       for (int i = 8; i < 11; ++i)
        pinMode(i, OUTPUT);
    }
    static int temp = DHT11.fahrenheit();
    static int digit_0 = temp % 10;
    static int digit_1 = temp - digit_0;
    static int digit_2 = digit_1 / 10;
    // Output pins.
    static int output[] = {0,1,2,3};
    // 8421 code lookup table.
    static int segs_encoding[][4] =
      {{0,0,0,0},   //=0
        {0,0,0,1},  //=1
        {0,0,1,0},  //=2
        {0,0,1,1},  //=3
        {0,1,0,0},  //=4
        {0,1,0,1},  //=5
        {0,1,1,0},  //=6
        {0,1,1,1},  //=7
        {1,0,0,0},  //=8
        {1,0,0,1}}; //=9
    // Outputs an 8421 decimal digit on the output pins from
    // base to base + 3 in big endian order.
    void show(int base, int num) {
     for (int i = 0; i < 4; ++i) {
       if(segs_encoding[num][i] == 1) {
         digitalWrite(base + 3 - i , HIGH);
       } else {
         digitalWrite(base + 3 - i , LOW);
       }
      }
    }
    // Output a 2 digit decimal value.
    void show_2digit_decimal(int num) {
    // force value to displayable range because show() doesn't do any sanity
      if (num < 0)
        num = 0;
      if (num > 99)
        num = 99;
      // display it.
      show(0, num);
      show(8, num/10);
    }
    void loop() {
      static int i = 0;
      show_decimal(i);
      delay(1000);
    // Increases the counter.
      ++i;
      if (i == 10)
        i = 0;
    }

Let me know if you guys need pictures of my breadboard set up, thanks for any help you guys can provide.

title: Temperature on two 7-segments displays

Answers: 2

body:
The `show()` function already has support for specifying the first pin of the display. So if the second digit is starting at pin 8 and connected in the same order then it should be as simple as:

    // Output a 2 digit decimal value.
    void show_2digit_decimal(int num) {
      // force value to displayable range because show() doesn't do any sanity checks
      if (num < 0)
        num = 0;
      if (num > 99)
        num = 99;
      // display it.
      show(0, num);
      show(8, num/10); // int/int always rounds down to the nearest int
    }

You will also have to add the appropriate `pinMode(<pin>, OUTPUT);` commands to the `setup()` function to make the pins outputs.

----- update

To get the temperature to display first get rid of these lines, they aren't doing anything useful

    static int temp = DHT11.fahrenheit();
    static int digit_0 = temp % 10;
    static int digit_1 = temp - digit_0;
    static int digit_2 = digit_1 / 10;

And then change the loop function to being

    void loop() {
      show_2digit_decimal(DHT11.fahrenheit());
      delay(500);
    }

Although unless the teacher is completely incompetent you should have been able to work that out yourself, it's not exactly rocket science. If unsure take a guess and try it first before asking. The logic is simple enough that you should be able to work it out. For syntax errors the compiler error messages will normally tell you exactly what's wrong.

body:
There are many issues with this code:

* The compiler says “_error_: ‘show_decimal’ _was not declared in this
  scope_”. Indeed, you named the function `show_2digit_decimal()`, so
  you should call it by that name.
* The compiler also said: “_warning: ‘output’ defined but not used_”.
  There is no valid reason to leave something defined that you do not
  use. Just remove it.
* You also have a function named `sertup()` that you defined but never
  used. It looks like a typo. You should remove the function, and put
  it's current contents inside `setup()`.
* You have the variables `digit_0`, `digit_1` and `digit_2` that serve
  no useful purpose. Remove them as well.
* You wrote, at top level: `static int temp = DHT11.fahrenheit();` Don't
  do this. This kind of initialization happens before `setup()`, i.e.
  before you had a chance to `attach()` the sensor to its pins.
* Your array `segs_encoding` is **not** a 7-segment encoding, it's just
  the binary encoding of the numbers. You don't need it: the processor
  already knows how to count in binary, and you can replace
  `segs_encoding[num][i]` by `num>>i&1`. If you really have 7-segment
  displays, you need 7 pins for each, unless you multiplex them. Search
  this site for “7 segment” to see how to drive them.
* The section
  `if(segs_encoding[num][i] == 1) { digitalWrite(base + 3 - i , HIGH); ...`
  can be simplified to
  `digitalWrite(base + 3 - i , segs_encoding[num][i]);` or, considering
  the previous point, to `digitalWrite(base + 3 - i , num >> i & 1);`
* The test `if (num < 0) num = 0; if (num > 99) num = 99;` can be
  written more succinctly by using the function Arduino provides for
  that: `num = constrain(num, 0, 99);`
* In `loop()`, you are only displaying a counter. You probably should
  display the temperature instead.

All the previous comments lead to the following version of the code:

<!-- language: lang-c++ -->

    #include <dht11.h>

    const int units_base_pin = 0;  // units on pins 0..3
    const int tens_base_pin = 8;   // tens on pins 8..11

    dht11 DHT11;

    // Outputs a number in binary on the output pins from
    // base to base + 3 in big endian order.
    void show(int base, int num) {
        for (int i = 0; i < 4; ++i) {
            digitalWrite(base + 3 - i , num >> i & 1);
        }
    }

    // Output a 2 digit decimal value.
    void show_2digit_decimal(int num) {
        // force value to displayable range because show() doesn't do any sanity
        num = constrain(num, 0, 99);
        // display it.
        show(units_base_pin, num);
        show(tens_base_pin, num/10);
    }

    void setup() {
        DHT11.attach(4);
        for (int i = 0; i < 4; ++i)
            pinMode(i, OUTPUT);
    }

    void loop() {
        show_2digit_decimal(DHT11.fahrenheit());
        delay(1000);
    }


body:
I have a program which estimates battery capacity, range as well as runs different control loops on an arduino MEGA2560 to control an eBike. I was using floating points which gave me quite a slow sampling frequency (10Hz). I now changed this to use integers by multiplying everything by at least 1000 so I can still keep a 3 decimal accuracy. However, as soon as the Arduino leaves setup and starts running loop, it crashes and restarts. I have a doubt that this could be due to the fact that my program takes too much RAM. How could I solve this?

Here is my code:

        #include <EEPROM.h>
        #include <memorysaver.h>
        //#include <TFT_HX8357.h> // Hardware-specific library
        #include <URTouch.h>
        #include <URTouchCD.h>
        #include <memorysaver.h>
        #include <UTFT.h>

        //TFT_HX8357 myGLCD = TFT_HX8357();       // Invoke custom library#include <TFT_HX8357.h> // Hardware-specific library
        //
        //TFT_HX8357 myGLCD = TFT_HX8357();       // Invoke custom library

        UTFT myGLCD(ILI9481,38,39,40,41);
        URTouch myTouch(6, 5, 4, 3, 2);

        int  buttonst, horn=5, throttle=8, powermode=1, alarmsystem=1, xtouch, ytouch, k1=0, k2=0,modechange,ncycles, p=9, divider=12, addresstd=0, kpow[3]={0,0,0}, kcur[3]={25,0,0}, ksp[3]={0,0,0};
        long pushed, pushedt, timesp, timespm1, powtimesm, factor, powtimesp, start, elapsed, powtime, powresttime, shuntvoltage, batvoltage, current, power, consumah, capacstore, consumwh, consumbatper, consumbatrange, distance, distanceint, throttlein, throttleout, distancedisp, Totaldist, velocity, Totaldistcheck;
        long throttlesmooth, capaccheck, capacactual,consumahstore, errorpower[2], errorpoweri, errorpowerli, errorcuri, errorcurrent[2], errorpowerl[2], diff, errorspeed[2], errorisp, outspeed, outcurrentctl, outspeedctl, elapsedtot, errorsmooth[2];
        float internresistance=0.00112;

        long batteryspec[6][56]={{4200,4000,3940,3900,3876,3860,3852,3844,3826,3809,3795,3783,3765,3744,3728,3710,3692,3672,3650,3631,3613,3591,3573,3556,3532,3508,3488,3463,3439,3417,3399,3380,3366,3352,3332,3312,3291,3273,3253,3237,3217,3196,3176,3150,3123,3087,3051,2994,2929,2868,2796,2727,2650,5261,2502},//5A discharge 18650GA SPEC
          {1,2,15,47,85,133,186,244,309,383,447,506,554,612,681,735,793,852,921,1007,1081,1150,1236,1300,1358,1438,1518,1587,1667,1747,1822,1888,1955,2014,2072,2152,2232,2317,2389,2466,2524,2594,2658,2722,2786,2847,2925,2983,3063,3133,3186,3245,3293,3330,3357,3368},
          {4200,4020,3980,3945,3927,3914,3904,3890,3874,3860,3843,3821,3797,3776,3756,3734,3713,3695,3675,3652,3634,3614,3593,3569,3543,3522,3500,3480,3459,3441,3419,3398,3378,3360,3339,3321,3301,3278,3254,3230,3199,3164,3128,3085,3037,2990,2937,2878,2837,2795,2746,2693,2648,2598,2549,2496},
          {0,7,33,84,151,223,294,377,457,521,574,646,718,785,851,931,1011,1091,1171,1251,1323,1397,1469,1547,1632,1701,1778,1853,1928,1994,2088,2175,2258,2333,2413,2487,2562,2634,2706,2775,2842,2908,2697,3023,3074,3116,3159,3205,3234,3261,3287,3314,3333,3352,3365,3379},//3A discharge 18650GA SPEC
          {4200,4131,4094,4073,4054,4038,4028,4015,4003,3985,3965,3945,3921,3894,3870,3850,3830,3811,3795,3775,3759,3739,3716,3692,3674,3648,3623,3601,3578,3561,3542,3522,3502,3486,3467,3445,3423,3401,3374,3350,3324,3291,3253,3210,3168,3123,3075,3026,2964,2897,2838,2781,2715,2652,2585,2502},
          {0,0,36,84,154,223,289,356,420,489,553,620,686,761,838,908,985,1054,1134,1214,1283,1358,1438,1523,1584,1667,1755,1835,1920,2002,2085,2170,2255,2327,2402,2482,2567,2644,2724,2791,2850,2908,2964,3015,3058,3095,3132,3167,3207,3245,3271,3295,3320,3336,3354,3365}}; //1A discharge 18650GA SPEC

        long cyclicspec[2][44]={{0,894,7151,16090,26400,37500,50950,61680,74190,85360,96540,107260,118880,130950,142120,154640,168040,182350,194860,208270,219890,234200,246700,262800,276200,291400,303900,317300,3271500,341500,354000,364000,374500,383460,395080,405800,418300,431700,444000,455900,468800,481900,491600,499700},
          {3441,3435,3342,3292,3235,3178,3121,3078,3014,2957,2921,2892,2842,2792,2750,2721,2679,2643,2607,2564,2543,2507,2479,2436,2407,2379,2357,2336,2336,2336,2336,2336,2336,2321,2300,2279,2271,2243,2229,2214,2193,2179,2164,2157}};

        extern uint8_t BigFont[];
        extern uint8_t SevenSegNumFont[];

        void EEPROMWritelong(int address, long value)
              {
              //Decomposition from a long to 4 bytes by using bitshift.
              //One = Most significant -> Four = Least significant byte
              byte four = (value & 0xFF);
              byte three = ((value >> 8) & 0xFF);
              byte two = ((value >> 16) & 0xFF);
              byte one = ((value >> 24) & 0xFF);

              //Write the 4 bytes into the eeprom memory.
              EEPROM.write(address, four);
              EEPROM.write(address + 1, three);
              EEPROM.write(address + 2, two);
              EEPROM.write(address + 3, one);
              }

        long EEPROMReadlong(int address)
              {
              //Read the 4 bytes from the eeprom memory.
              long four = EEPROM.read(address);
              long three = EEPROM.read(address + 1);
              long two = EEPROM.read(address + 2);
              long one = EEPROM.read(address + 3);

              //Return the recomposed long by using bitshift.
              return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
              }

        long pidcurrent_control() {

      long dt, outcurrent=0, outpower=0;
         int i=0, descurrent, despower;
         i++;
         dt=millis()-powtime;
         powtime = millis();
         if (powermode==1) { //Furo default mode
          if (current>40000) {
            descurrent=40000;
            errorcurrent[1]=descurrent-current;
            if (i>=2) {
              //Integrate the error
            errorcuri+=errorcurrent[1]*dt;

            outcurrent=(kcur[0]*errorcurrent[1]+kcur[1]*errorcuri+kcur[2]*((errorcurrent[1]-errorcurrent[0])/dt));
            }
            errorcurrent[0]=errorcurrent[1];
            return outcurrent;
            }
            if (((batvoltage*current)/1000)>2000000) {
             despower=2000000;
              errorpower[1]=despower-batvoltage*current/1000;
              if (i>=2) {
            //Integrate the error
            errorpoweri+=errorpower[1]*dt;
            outpower=kpow[0]*errorpower[1]+kpow[1]*errorpoweri+kpow[2]*((errorpower[1]-errorpower[0])/dt);
            }
            errorpower[0]=errorpower[1];
            return outpower;
            }
            }
          else { //Eco mode
           despower=550000;
           errorpowerl[1]=despower-batvoltage*current/1000;
              if (i>=2) {
              //Integrate the error
              errorpowerli+=errorpowerl[1]*dt;
              outpower=kpow[0]*errorpowerl[1]+kpow[1]*errorpowerli+kpow[2]*((errorpowerl[1]-errorpowerl[0])/dt);
            }
            errorpowerl[0]=errorpowerl[1];
            return outpower;
            }
            }

        void cyclescaling() {
        int j=1;
         if (ncycles<=499000) {
         while ((ncycles<cyclicspec[0][j-1])||(ncycles>cyclicspec[0][j])){
                   j++;
            }
            factor=(cyclicspec[1][j-1]+(ncycles-cyclicspec[0][j-1])*(cyclicspec[1][j]-cyclicspec[1][j-1])/(cyclicspec[0][j]-cyclicspec[0][j-1]))/cyclicspec[1][0];
        }
        else {
            factor=(cyclicspec[1][41]+(ncycles-cyclicspec[0][41])*(cyclicspec[1][42]-cyclicspec[1][41])/(cyclicspec[0][42]-cyclicspec[0][41]))/cyclicspec[1][0];
        }
        }

        long pidspeed_control() {
        int isp, dtsp;
        isp++;
        dtsp=millis()-powtimesp;
        powtimesp = millis();
        errorspeed[1]=46000-velocity;
        if (isp>=2) {
            errorisp+=errorspeed[1]*dtsp;
            outspeed=(ksp[0]*errorspeed[1]+ksp[1]*errorisp+ksp[2]*((errorspeed[1]-errorspeed[0])/dtsp));
            }
            errorspeed[0]=errorspeed[1];
            return outspeed;
        }

        void throttlesmoothing() {
         int i=0, dtsm;
         i++;
        long currentmap=map(throttlein,800,3600,0,40000);
         dtsm=millis()-powtimesm;
         powtimesm = millis();
         errorsmooth[1]=currentmap-current;
              if (i>=2) {
              //Integrate the error
              throttlesmooth=kcur[0]*errorsmooth[1];//+kcur[2]*((errorsmooth[1]-errorsmooth[0])/dtsm);
            }
            errorsmooth[0]=errorsmooth[1];
        }

        void SOC() {
          int currentref=current/p, compbat=batvoltage/14;
          int j=1,l=1;
          long stateofc1=0, stateofc2=0;

          if (currentref<=1000){
            while (((compbat)>batteryspec[0][j-1])||((compbat)<batteryspec[0][j])){
                   j++;
            }
            capacactual=(batteryspec[1][55]-(batteryspec[1][j-1]+(compbat-batteryspec[0][j-1])*(batteryspec[1][j]-batteryspec[1][j-1])/(batteryspec[0][j]-batteryspec[0][j-1])))*p;
            Serial.println("\n");
            Serial.println(current);
                Serial.println(batvoltage);
                    Serial.println(batteryspec[1][j-1]);
          }

         if ((currentref>1000)&&(currentref<=3000)){
            while (((compbat)>batteryspec[0][j-1])||((compbat)<batteryspec[0][j])){
                   j++;
            }
            stateofc1=(batteryspec[1][55]-(batteryspec[1][j-1]+(compbat-batteryspec[0][j-1])*(batteryspec[1][j]-batteryspec[1][j-1])/(batteryspec[0][j]-batteryspec[0][j-1])))*p;

             while (((compbat)>batteryspec[2][l-1])||((compbat)<batteryspec[2][l])){
                   l++;
            }
            stateofc2=(batteryspec[3][55]-(batteryspec[3][l-1]+(compbat-batteryspec[2][l-1])*(batteryspec[3][l]-batteryspec[3][l-1])/(batteryspec[2][l]-batteryspec[2][l-1])))*p;
            capacactual=stateofc1+(currentref-1)*(stateofc2-stateofc1)/(3000-1000);
          }

           if ((currentref>3000)&&(currentref<=5000)){
            while (((compbat)>batteryspec[2][j-1])||((compbat)<batteryspec[2][j])){
                   j++;
            }
        //    stateofc1=(batteryspec[3][55]-(batteryspec[3][j-1]+(compbat-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p;

             while (((compbat)>batteryspec[2][l-1])||((compbat)<batteryspec[2][l])){
                   l++;
            }
        //    stateofc2=(batteryspec[3][55]-(batteryspec[3][l-1]+(compbat-batteryspec[2][l-1])*(batteryspec[3][l]-batteryspec[3][l-1])/(batteryspec[2][l]-batteryspec[2][l-1])))*p;
            capacactual=(batteryspec[3][55]-(batteryspec[3][j-1]+(compbat-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p+(currentref-1)*((batteryspec[5][55]-(batteryspec[5][l-1]+(compbat-batteryspec[4][l-1])*(batteryspec[5][l]-batteryspec[5][l-1])/(batteryspec[4][l]-batteryspec[4][l-1])))*p-(batteryspec[3][55]-(batteryspec[3][j-1]+(compbat-batteryspec[2][j-1])*(batteryspec[3][j]-batteryspec[3][j-1])/(batteryspec[2][j]-batteryspec[2][j-1])))*p)/(5000-3000);

          }

        if (currentref>5000) {
           while (((compbat)>batteryspec[4][j-1])||((compbat)<batteryspec[4][j])){
                   j++;
            }
            capacactual=(batteryspec[5][55]-(batteryspec[5][j-1]+(compbat-batteryspec[4][j-1])*(batteryspec[5][j]-batteryspec[5][j-1])/(batteryspec[4][j]-batteryspec[4][j-1])))*p;
        }

        }

        void autonomy() {

          if (modechange==1) {
           consumah=0;
          }

            power=batvoltage*current/1000;
            SOC();

            if (capacactual!=capaccheck) {
              capaccheck=(capacactual+capaccheck)/2;
            }

          if (abs(capacactual-capacstore)>=100){
             EEPROMWritelong(8,roundf(capacactual));
             capacstore=capacactual;
          }

          consumah += 1000*current*elapsed/1000/3600;
          capaccheck -= 1000*current*elapsed/1000/3600;
          consumwh += 1000*current*elapsed/1000/3600*batvoltage;
          elapsedtot += elapsed;
          consumbatper = (capaccheck)/(batteryspec[1][55]*p)*100;
          if (distance==0) {
            switch (powermode) {
              case 1: consumbatrange=45*batvoltage*capaccheck/980;
              break;
              case 2: consumbatrange=35*batvoltage*capaccheck/550;
              break;
            }

          } else {
          consumbatrange = distance/consumah*(capaccheck);
          }
          myGLCD.printNumI(consumbatrange/1000, 2, 350,275);
          myGLCD.printNumI(power/1000, 2, 350,205);
          myGLCD.printNumI(current/1000, 1, 30,50);
          myGLCD.printNumI(ncycles/1000, 1, 30,50+16*2);
          myGLCD.printNumI(consumbatper,1,350,50);
          myGLCD.printNumI(batvoltage/1000,1,350,50+16*2);

          return 0;

        }

        void speedometer() {
        int sense=digitalRead(46);
        long sensecst=691150*3;//x1 000 000

        if (sense==LOW) {
           timesp=millis()-timespm1;
           timespm1 = millis();
           velocity=3600/1000*sensecst/(timesp);//m/h
           if (timesp>1000) {
               velocity=0;
           }
        } else {
          if ((millis()-timespm1)>2000) {
            velocity=0;
          }
        }
        }

      void setup() {
          // put your setup code here, to run once:
          Serial.begin(9600);
          start=millis();
         // pinMode(43, OUTPUT);//Speedo power
         // pinMode(46, INPUT);//Speedometer
          pinMode(A2, INPUT);//Throttle in
          pinMode(A7, INPUT);//Battery voltage
          pinMode(A4, INPUT);//Shunt
          pinMode(throttle, OUTPUT);
          pinMode(11, OUTPUT);
          pinMode(10, OUTPUT);
          pinMode(47, INPUT);
          analogWrite(10,255);
          analogWrite(11,255);

          myGLCD.InitLCD(LANDSCAPE);
          myTouch.InitTouch(LANDSCAPE);
          myGLCD.fillScr(0,0,0);
          myGLCD.setColor(VGA_WHITE);
          myGLCD.setBackColor(0,0,0);
          myGLCD.setFont(BigFont);
          myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
          myGLCD.print("WELCOME",(480-16*7)/2,(320-16)/2);
          myGLCD.setDisplayPage(0);
          delay(2000);
          myGLCD.clrScr();
          myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
          myGLCD.fillRoundRect((480-3*16-8)/2,320-16*2-4,(480-3*16-8)/2+3*16+6,228);
          myGLCD.print("ECO", (480-3*16)/2, 320-16*5);
          EEPROMWritelong(4,1000);
          ncycles=EEPROMReadlong(4);
          cyclescaling();

          for (int m=1; m<=5;m+=2) {
          for (int n=0; n<=55;n++) {
            batteryspec[m][n]*=factor;
            }
          }

          current=analogRead(A4);
          current=current/internresistance*5*1000/1023/75;

          batvoltage=analogRead(A7);
          batvoltage=batvoltage*5*1000*divider/1023;

          SOC();
          capaccheck=capacactual;
          capacstore=EEPROMReadlong(8);

          if (capacactual>capacstore) {
          ncycles+=1000;
          EEPROMWritelong(4,ncycles);
          EEPROMWritelong(8,roundf(capacactual));
          }

          if (capacactual<500) {
            powermode=2;
            myGLCD.fillRoundRect((480-4*16-8)/2,320-16*2-4,(480-4*16-8)/2+4*16+6,228);
            myGLCD.print("FURO", (480-4*16)/2, 320-16*5);
          }//3.21V per cell
          EEPROMReadlong(addresstd);
          Totaldist=EEPROMReadlong(addresstd);
          Totaldistcheck=Totaldist;
          digitalWrite(43,HIGH);
        }

        void loop() {
           throttlein=analogRead(A2);
           throttlein=throttlein*5*1000/1023;
           //throttlesmoothing();
           throttleout=throttlein/1000*255/5;
           analogWrite(8,throttleout);

           modechange=0;
            if (digitalRead(47)==LOW)
            {
              if (buttonst==1) {
              pushed = millis();
              }
              buttonst=0;

              if ((millis()-pushed)>=2000)
              {
               distancedisp=0;
              }
              }

             if (digitalRead(47)==HIGH) {
              if (buttonst==0) {
                modechange=1;
                pushedt=millis()-pushed;
                if (pushedt<1900){
               if (powermode==1)
              { powermode=2;
               myGLCD.clrScr();
               myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
               myGLCD.fillRoundRect((480-4*16-8)/2,320-16*2-4,(480-4*16-8)/2+4*16+6,228);
               myGLCD.print("FURO", (480-4*16)/2, 320-16*5);
              }
              else
              {
                powermode=1;
                myGLCD.clrScr();
                myGLCD.print("FURO SYSTEMS",(480-16*12)/2,16);
                myGLCD.fillRoundRect((480-3*16-8)/2,320-16*2-4,(480-3*16-8)/2+3*16+6,228);
                myGLCD.print("ECO", (480-3*16)/2, 320-16*5);
              }
              }
              }
              buttonst=1;
             }

        batvoltage=analogRead(A7);
        batvoltage=batvoltage*5*divider*1000/1023;
        //speedometer();
        current=analogRead(A4);
        current=current/internresistance*5*1000/1023/75;
        elapsed = millis() - start;
        start = millis();

        if (modechange==1) {
           distance=0;
        }
        distanceint = (velocity/3600*elapsed/1000);//m
        distance += distanceint;
        distancedisp += distanceint;
        Totaldist += distanceint;

        if (abs(Totaldist-Totaldistcheck)>=100) { //later do it upon switch off
          EEPROMWritelong(addresstd,round(Totaldist));
          Totaldistcheck=Totaldist;
        }

        autonomy();

        if (velocity>45000) {
        outspeedctl=pidspeed_control();
        outcurrentctl=pidcurrent_control();
        long throttleout1=min(outspeedctl,outcurrentctl);
        throttleout=min(throttleout1,throttlesmooth);
        //analogWrite(throttle, map(throttleout, 0,5,0,255));
        } else{
        outcurrentctl=pidcurrent_control();
        throttleout=min(throttlesmooth,outcurrentctl);
        //analogWrite(throttle, map(throttleout, 0,5,0,255));
        }

        myGLCD.setFont(SevenSegNumFont);
        myGLCD.printNumI(velocity, (480-32*3)/2, (320-50)/2);
        myGLCD.setFont(BigFont);
        myGLCD.printNumF(distancedisp, 1, 30,175);
        myGLCD.printNumI(Totaldist, 30,175+2*16);

        }

title: Float to integer conversion for control program crashes arduino

Answers: 1

body: I actually solved this issue and noticed a few things for those interested: the printNumI() function was making the arduino crash as it was badly initiated with an extra argument. Once I solved this and replaced all my printNumF with printNumI I noticed a significant increase in sample rate of about 3-4ms per line changed. In addition, going from float to int calculation didn't change much as the TFT screen takes enormous amounts of computing power: takes me from 333Hz of sampling frequency to about 10Hz with the screen.


body:
I need to connect the data of a LED strip (WS2812) to a pin but the strip is 10 meters away using AWG 22.
I use a 12V DC power supply.
Should I expect some misbehaviour, like the LED not getting the right color ?
If so, what could I do ?

title: Long run data wire

Answers: 1

body:
If you are planning to power the LED strip from 12V then you can expect all the LEDs to explode. The WS2812 LEDs require 5V, not 12V.

If you have a large number of WS2812 in your strip, and you are powering them from the Arduino's 5V, then you can expect the Arduino to get extremely hot and go into thermal shutdown, or the voltage regulator to melt.

If you are in a noisy environment (electrically) then you can expect the data to get corrupted over that kind of distance.

What you should do:

1. Provide 5V to the LED strip from a power supply or regulator that can cope with the amount of current your LED strip needs.
2. Have another small Arduino next to the LED strip to drive the LEDs and communicate with that Arduino from your master Arduino through a suitable serial protocol that can cope with longer distance communications, or a wireless system.


body:
I bought a 100 pack of WS2812S SMDs last year (product link) and wired most of them together for a string of Christmas lights for a tree. It was more work, but way cheaper (at the time) than buying a strip.

I had a few left over that I kept stored away until tonight when I decided to work up a little circuit to enhance my wife's Halloween costume. Problem is, I can't get them to light. Initially I had 3 soldered together, making sure that the voltage and data were going in the right direction, but when I plugged them into my Arduino Uno with a very basic NeoPixels based sketch, none would light. Figuring I had a bad one, I desoldered them all and tried, one by one, on a breadboard. Still no joy.

I tested and confirmed with a multimeter that I was getting the required voltage from one LED to another and reading voltage on the DIN/DOUT pins, but never any light. If I put the Christmas strand from last year on the same pins it works great.

Is there anyway to tell if these are just bad LEDs, or have I missed a step somewhere? I figured if the multimeter showed no voltage on one or more of the pads, that would be an obvious sign to trash it, but since all three show voltage, both when wired together and separately, I can't figure a reason they shouldn't light. Is there more I can do to test?

title: Testing for bad WS2812B?

Answers: 0


body:
I am moving my Arduino Uno project from Uno to Bread and as we know, this requires two 22 pf capacitors and 16 MHz on the breadboard (and the other things too like the power-but my question is about the crystal frequency so I'll focus on that).

If I replace the 16 MHz crystal with a 12 MHz crystal then the project will work as expected on a breadboard-is that correct?

It seems that the fuse setting to use 16 MHz crystal is the same as for the 12 MHz crystal for Arduino Uno-so I guess a change to the fuse setting or bootloader is not required. Am I missing anything?

I guess it's as simple as replacing a 16 MHz crystal by a 12 MHz crystal.

title: Using Arduino project migrated to breadboard with 12 MHz crystal instead of 16 MHz

Answers: 2

body:
Yes it will work correctly IF you change the compile setting so that everything is in sync. This is because when you select an Arduino UNO from the IDE, it will process that as if your Arduino has 16Mhz. [Here is a link for more information.][1].

  [1]: http://forum.arduino.cc/index.php?topic=26372.0

body:
Some of the code running on the microcontroller needs to know the clock speed it's running at for correct timing. For this reason the macro `F_CPU` is set with this value. In the Arduino IDE this value is commonly defined in the [boards.txt](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification#boardstxt) `build.f_cpu` property. If you're using a bootloader(which is used for uploading sketches over serial) it also needs to know the clock speed so that it can get the baud rate of the upload correct. The bootloader is not compiled in the Arduino IDE so it is not affected by your setting in boards.txt. You can recompile the bootloader with the correct clock speed setting and then install the compiled file on your microcontroller using an ISP.

There is a much more simple solution. All the hard work has already been done for you in MiniCore:
https://github.com/MCUdude/MiniCore

You only need to:

1. Install MiniCore following the instructions at https://github.com/MCUdude/MiniCore
1. Tools > Board > ATmega328
1. Tools > Variant > 328P / 328PA
1. Tools > Clock > 12 MHz external
1. Tools > Burn Bootloader