# Question
Title: Extrapolate require MCU from Arduino MEGA2560 performance
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);

}

```

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

---
Tags: atmega2560, performance
---


title: How to switch 12V water pump

text:
# Question
Title: How to switch 12V water pump
I found this pump:

https://www.aliexpress.com/item/Free-Shipping-Ultra-quiet-DC-12V-3M-240L-H-Brushless-Submersible-Water-Pump-High-Qualtiy-mini/32472119699.html

Now, I want to control it from an Arduino.

Is this a good relay to use?

https://www.pololu.com/product/2480?

I want to use a 12v battery for the pump.

# Answer
> 1 votes
I see people are recommending mosfets (which is the best option). Keep reading this if you still want to use relay. There are two kind of relays, mechanical and solid state. Mechanicals are cheap but they can be noisy (they make sound) also they have low life expectancy compared to solid state relays. On the other hand solid state relays are faster with everything else but they are expensive. Also you need to check voltage and max current rates before buying.

# Answer
> 1 votes
About the relay, you can buy a low cost relay from aliexpress like the following one or other variant.

https://m.aliexpress.com/item/32392799916.html#autostay

It's well within your desired voltage and current range and works readily with arduino.

---
Tags: motor, relay
---


# Question
Title: Change from using the external crystal to the internal oscillator
**BACKGROUND**

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

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)

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

---
Tags: pwm, millis, frequency, oscillator-clock
---


# Question
Title: Format hour and minute integers to HH:MM format (char*)
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]

```

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

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

# Answer
> 1 votes
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("%02d:%02d"), _hour, _minute); // format string resides in flash (it needs special version of sprintf.
  // sprintf(buff, "%02d:%02d", _hour, _minute); // usual variant, but format is stored in RAM (and Flash too)

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

```

---
Tags: time, variables
---


# Question
Title: Help to get Arduino UNO with 4 SoftwareSerial transmit only ports
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);

  }
}

```

# Answer
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 \- 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. You could have a single SoftwareSerial instance, and then use the multiplexer to forward its data to one of (up to 8) pins.

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

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

---
Tags: arduino-uno
---


# Question
Title: How to convert this prototype to finished product?
My prototype contains below components:

I think It's OK on paper (and presumably on a breadboard too). I'm trying to wrap my head around on how to convert it to a finished product that sits inside a plastic box.

**What are my options?**

For instance, can I create a single PCB that contains all the components? If not, how can I connect these multiple break-out boards together? Is soldering some wires on both boards to connect them is a viable option?

**Edit:**

My ultimate goal is to create a product that is for sale. So I mean something that can be mass-produced and can meet regulatory requirements.

This is why I was thinking about a single PCB. Arduino (or should I say ATMegaXXX?) is fairly simple to place on a custom PCB. So I was thinking perhaps I could "re-create" my break-outs (see above) on this PCB thus creating a single piece including all components and the microcontroller. For some reason this makes sense to me but I don't know how hard it is or if it is even possible.

# Answer
> 3 votes
First, you should read this this question here.

The reasonable answer here varies a lot depending on how involved you want to get, and what volumes you want to sell at.

Fortunately, you're not using any breakouts with truly exotic parts. The nRF8001 is just a QFN part, which can be soldered by hand without too much trouble.

Speaking loosely, the process would look like this:

1. Design a PCB layout that contains everything.
2. (Optional) - Figure out if you want to put it in a enclosure of some sort.
3. (Optional) - Determine how you're going to have the enclosures produced or modified from an existing product. You can have a contract machine-shop do the work, but again, $$$$.
4. Send out to have PCB prototypes manufactured. I like OSHPark, but there are LOTS of options.
5. Assemble your boards.
6. Find out your prototype doesn't work.
7. Go back to step 1 (expect this to happen a few times)
8. Rent/Beg/Borrow some equipment to do EMC pre-qualification testing (for FCC).
9. Realize you have an EMC disaster.
10. Respin boards a few more times (e.g. go back to 1 again) to fix the pre-qualification EMC issues.
11. Feel like you have a decent layout, have it FCC tested.
12. Pay $10K+ for FCC testing.
13. If you're lucky, you passed, you now have a proper, FCC certified product.
14. Nope, go back to 1 again if you failed.
15. Do lot assembly, either manually (major time investment), or contract out (expensive!).
16. Sell your widget!

Note that you can contract out the prototype assembly, but doing so is *expensive*, even if you do it in china. The magic (or cursed, really) term here is "NRE", or non-reoccurring expenses/engineering. Colloquially, it's the "setup cost" of doing a production run. Sure, you may only pay $5-50 per-widget to have them assembled, but there will be a $1000+ base charge. This reflects the fact that the primary time-cost on the part of an assembly house to build your widget is setting up the production line, working up and debugging a pick-and-place routine, building test-setups, etc... Once everything is up and running, the actual per-unit cost is fairly marginal.

This is also why commercial electronic devices can be so cheap. They're made in truly enormous volumes, and that lets the companies amortize the NREs across the entire production run. NREs are basically the bane of any small electronics business. They're also basically *the* reason specialty widgets are so expensive. Places like spark-fun can get away with fairly cheap products because they have their own complete assembly line in-house, and even there, you're often paying 4X+ the cost of parts for just the IC on a PCB with a few cents worth of passives.

Since you seem to be new to PCB design, this is possibly not a great first project. It's doable, but expect it to cost 4X+ what you expect, and take 2X+ the time you planned. There are a LOT of facets to designing a proper product, and they each contain an entire field.

It'd probably be better off to start out with some simpler boards, maybe a through-hole-only arduino clone, or similar (though SOIC can be soldered without a hot-air station or anything).

---

Some assumptions I'm making:

* If you're serious, you will *have* to lean SMT assembly practices. Through-hole only is not a viable stance anymore.
* Expect to buy a lot of tools, and burn a lot of money in failed prototypes.
* Expect 3 board revisions. **At minimum**, before you have something you can get tested. I could maybe do it in 2, if I got really, *really* lucky, but I doubt that would happen, and this sort of thing is my day-job.

Hardware is HARD, and worse, it's completely unforgiving. If you're coming from a software engineering background, you basically have to discard all your assumptions, as they will actively hurt you.

Imagine a software project where "compiling" can take 4 weeks. That's hardware development.

# Answer
> 0 votes
By "product", do you mean for sale? Giveaways to friends? One for yourself? How many do you expect to make? It isn't (monetarily) worth creating a board for one or five pieces unless you want to for reasons of aesthetics, reliability, demonstrating your skills to a potential employer, etc. OTOH, if you sell a product, it will to meet regulatory requirements in the jurisdiction(s) in which you intend to sell it. So the - admittedly unsatisfying - answer is: it depends. :) (In other words, we need more information).

Chinese board houses advertise they can do small runs for quite reasonable prices, but expect to spin the board several times unless it's a pretty simple one. Not dissing their abilities or skills as I have no experience with any of them, but as a practical matter of communicating exactly what you want, the first time, to a business half a planet away, a business you might not be familar with yet, and someone with whom you might not share a native language. Even with those obstacles out of the way, boards can take several- to many spins to get to a first production revision.

For a small handful of boards (depending the size of a "handful"), hand-wiring on hobby PCBs or strip-boards can be effective and not too expensive.

# Answer
> 0 votes
**step1: Make the hardware**

* Refer the schematics of arduino you are using and make your own pcb
* Approach any PCB manufactures and deliver them your GERBER files with correct Bill of Materials.
* You can easily make a single PCB. consider PCB with components on both sides, and multi stackable PCB only if the dimension of required PCB matters.
* Try not to place nRF antenna and crystal for the micro controller close to each other.

**Step2: Firmware**

This step is about getting .hex file from arduino code and givin this to the same pcb manufacturer, with proper fuse values

* Go to file-\>preferences in arduino
* Check show verbos
* open the temp file (type %temp% on RUN)
* Compile your arduino code. this will generate a build folder inside temp folder Search for yourArduinoProjectName.hex inside that folder.

*This is the code you need to get fuse bits*

```
#include <avr/boot.h>;
void setup() { Serial.begin(57600);

cli();
uint8_t lowBits      = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
uint8_t highBits     = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
uint8_t extendedBits = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
uint8_t lockBits     = boot_lock_fuse_bits_get(GET_LOCK_BITS);
sei();

Serial.print("Low:  0x");
Serial.println(lowBits, HEX);
Serial.print("High: 0x");
Serial.println(highBits, HEX);
Serial.print("Ext:  0x");
Serial.println(extendedBits, HEX);
Serial.print("Lock: 0x");
Serial.println(lockBits, HEX);    }
void loop() { }

```

Or check the file

> C:\Program Files (x86)\Arduino\hardware\arduino\avr\boards.txt

to find the fuses.

# Answer
> -1 votes
Single PCB is not viable, as some chips are near impossible to solder by hand. Also, you'd have to get your PCB checked for FCC compliance (because of the bluetooth), which you don't want.

You could design a PCB that contains the Arduino micro controller (ATMega328), and that all the other board plug into.

Wires could also be a solution, by you probably need to find a way to securely mount all the boards inside the enclosure (no rattling).

PS I'd suggest something like an Arduino Nano as it's smaller, and you can remove the header pins and solder wires directly to PCB.

---
Tags: arduino-uno
---


# Question
Title: Which arduino should i use for a very simple one pin "blinking led" type project?
I want to simply switch a relay like Majenko describes it for my last question. (time based switching of a relay)

That's the code I came up with based on the documentation:

```
int relayPin = 2; // pin where relay is attached
long mins = 5L;

void setup() {
    pinMode(relayPin, OUTPUT);
}

void loop() {
    digitalWrite(relayPin, HIGH);
    delay(mins * 60L * 1000L);
    digitalWrite(relayPin, LOW);
    delay(mins * 60L * 1000L);
}

```

Now I want to use a real device and have been looking around, but there are tons of different boards, so some shopping advice would be really great. What I would like if possible:

* Closed casing to reduce risk of people touching stuff. (also for a "professional" look)
* Built in power supply from 220V AC.
* Outputs strong enough to work without external logic, just connect the relay and go.
* Small size and low cost, in case I start using these everywhere in the house i don't need to reevaluate. :)

# Answer
For beginners, use an Arduino Uno. It is ready to use and quite expendable with shields. They have the USB to SERIAL chip on the board. Only week point is that it is sometimes large from space sensitive projects.

For more advanced users, I would suggest the Pro Mini (my personnal favorite). It is small, powerful and even has more pins then the UNO. The main disadvantage is that it requires an FTDI connector for the USB to SERIAL. Note that this NOT recommended if you use a lot of I2C.

Finaly, there is the overkill option. Only use this if you are considering to get one Arduino to rule them all!. It's the Arduino Mega 2560. It is the overkill of the overkill. So many GPIOs and ANALOG inputs. It is also unique for its core which is different the then normal ATmega328.

Then finaly there is the most easy to use one, the Red Board by Sparkfun. It combines the best of each Arduino in one. Note that this one is not manifactured and backed by Arduino.

That is pretty much a summary of all of the most popular types of Arduino that there is.

**\[EDIT\]**

Note that none of them has an included case and a circuit that can reduce 220V to 5V. If you really want a case, get an UNO. There are many cases for it. For transforming 220V to 5V, use an 5V wallplug. If you have something like a 12V wallplug, you can also connect it to the Arduino but you have to make sure you connect it to the Vin port.
> 0 votes

# Answer
Personally I would recommend a chip from the ATtiny series (ATtiny85 for example - it has 5 programmable pins and costs about $1 - $3).

Even though it is not really an Arduino board - it is really great as you can easily program it from another board from within the Arduino IDE, and it is really lightweight and cheap.

Watch this Youtube video for a guide to set it up - it is really useful.

Otherwise you can simply give "*attiny85 arduino setup*" a google
> 1 votes

---
Tags: arduino-uno, arduino-nano
---


# Question
Title: How to analogRead() 2 separate pins simultanously?
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?

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

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

---
Tags: analogread, adafruit, proximity
---


title: Temperature on two 7-segments displays

text:
# Question
Title: Temperature on two 7-segments displays
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%10);
  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.

# Answer
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%10);
  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.
> 2 votes

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

```
#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%10);
    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);
}

```
> 1 votes

---
Tags: arduino-uno, arduino-ide
---


title: Long run data wire

text:
# Question
Title: Long run data wire
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 ?

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

---
Tags: led, wires
---


# Question
Title: Is there a cheap relay that can control voltage from stuff like bulb lights with a 5 V control output?
I need to power a light bulb or something like 110 V or 220 V at normal amperage for TV or something at that range like a fan...

My micro-controller is an Arduino with 5 V out and 12 V max out trough transistor switch.

To my understanding a stepper motor drive could be a viable option to enable the relays... I can even control current, right?

Up to 8 channels

Could this work better?

# Answer
**Which to use where**

Ok, so I've narrow the 2 main choices that you have : either a MOSFET or a RELAY. For higher voltages, it is much safer to go with a relay but for higher current, you might as well use a power MOSFET.

**Option 1 - Relays**

They are mainly used to control already made stuff like a bulb using main's voltage. They are also used to control stuff like a fan (pre built), lamp, and many more. Relays are also simple to wire and don't quire much electronics skills. The main disadvantage of a relay is that they are not as good as MOSFETs when it comes to current handling.

***Advantages: Light bulb, stuff bought from the sotre (TVs, fans, small heater), house automation, laundry, house heater, fridge***

**Opition 2 - MOSFETs**

**IMPORTANT NOTICE : YOU CANNOT USE A MOSFET WITH MAIN'S VOLTAGE**

MOSFETs are great when it comes to kick some voltage in to your devices. I remember as a kid, I use to stock these in NERF guns. Motors will instantly start with MOSFETS!. For even higher current control. Try power mosfets, they are designed for high current. Also know that mosfets are bad in the way that they tend to warm up a lot (if the current is high).

***Advantages: Neon light, motors, things that need to be responsive (drone motors), things that need to be precise (PWM)***

In conclusion, relays master the world of high voltages and MOSFETs the world of high current!
> 0 votes

# Answer
You can use a 5V Solid-State Relay module to control light bulbs. They cost $4-6 from US-based suppliers and $1-3 from a Chinese supplier. Just hook up the supply to the center pin and the load to either the NO or NC pin. Supply 5V to the module and wire a digital pin to the module to control it.
> 3 votes

# Answer
The first one you have seems fine (in my opinion). Note though that relays are something not to be cheap with. They can cause dangerous accidents if you buy them from a cheap supplier (chinese). I'll always go for a local supplier (don't know where you live so I can't tell). Make sure to check Radioshack and stores like that.

Also make sure that you find one with a datasheet. No datasheet = no specs. No specs = you don't know the max of your relay which is BAD. The max of a relay should be known and respected or something bad can happen.
> 1 votes

---
Tags: relay, mosfet, switch
---


title: Arduino Nano not showing up in /dev

text:
# Question
Title: Arduino Nano not showing up in /dev
When I plug in my nanoatmega328 to my computer, nothing shows up in `/dev` as I expect it to. If I plug in my Uno, `/dev/ttyACM0` shows up. I have tried several Nanos.

Linux Mint 17.2.

# Answer
> 3 votes
`dmesg` should be the tool to help you.

Run:

```
$ dmesg -w

```

Then hit return a few times (to get some blank lines).

Next plug in your Nano. Some text should appear on the screen, which will give you a clue as to what is going on. I don't have a Nano to try with, but a typical working device would look something like:

```
[29125.599800] usb 9-1.4.1: new full-speed USB device number 13 using ehci-pci
[29125.694742] usb 9-1.4.1: New USB device found, idVendor=04d8, idProduct=0208
[29125.694747] usb 9-1.4.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[29125.694749] usb 9-1.4.1: Product: Lenny
[29125.694751] usb 9-1.4.1: Manufacturer: chipKIT
[29125.694753] usb 9-1.4.1: SerialNumber: CK1660A05353C5
[29125.695213] cdc_acm 9-1.4.1:1.0: This device cannot do calls on its own. It is not a modem.
[29125.695240] cdc_acm 9-1.4.1:1.0: ttyACM0: USB ACM device
[29125.695768] cdc_acm 9-1.4.1:1.2: This device cannot do calls on its own. It is not a modem.
[29125.695791] cdc_acm 9-1.4.1:1.2: ttyACM1: USB ACM device
[29125.697772] input: chipKIT Lenny as /devices/pci0000:00/0000:00:1a.7/usb9/9-1/9-1.4/9-1.4.1/9-1.4.1:1.4/0003:04D8:0208.0004/input/input19
[29125.698394] hid-generic 0003:04D8:0208.0004: input,hidraw2: USB HID v1.11 Mouse [chipKIT Lenny] on usb-0000:00:1a.7-1.4.1/input4

```

If it doesn't know what the device is it will give you a fraction of the information, and probably tell you it can't attach a driver.

If the device is faulty and not recognisable you will get messages similar to:

```
[29125.698394] usb 2-2.1: device not accepting address 5, error -71

```

If you get absolutely nothing displayed then it can't even recognise that anything has been attached to your computer. Try different USB sockets and different USB cables to see if that helps.

Note: some cheap USB cables used purely for charging small batteries don't have any data wires in them - just power. Using one of these will fail for sure.

# Answer
> 1 votes
Did you try with `lsusb` and `dmesg`?

They should show if the Arduino was detected and what are its parameters (use `lsusb -v` for more detailed info).

If it is detected but you do not get the corresponding tty device, it might be because of missing/different rules.

You could check out this link and edit the parameters idProduct and idVendor to match what you get from `lsusb`, in case your rule is not matching.

Then remember to reload the modified rules.

Protip: compare the parameters of your working Uno against the ones from the Nanos and the values set in the rules.

# Answer
> 0 votes
Like Majenko said, if dmesg shows nothing then your cable could be to blame. It could be for power only (no data lines). This happened to me. I wouldn't have even thought of the cable if I did not read it here. My hardware is also Arduino nano clone (atmega238 + ch340) and the machine runs Ubuntu 15.04. With a good cable the device is recognized like this (dmesg -w):

```
usb 4-2: new full-speed USB device number 24 using ohci-pci
usb 4-2: New USB device found, idVendor=1a86, idProduct=7523
usb 4-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
usb 4-2: Product: USB2.0-Serial
ch341 4-2:1.0: ch341-uart converter detected
usb 4-2: ch341-uart converter now attached to ttyUSB0

```

---
Tags: arduino-nano, port-mapping
---


title: IRemote with PulseSensor

text:
# Question
Title: IRemote with PulseSensor
I have a problem with these two modules. I am trying to create a pulse sensor but also want to use a remote for some further functionality (menu system). I have the code separated into two files, one for the main menu and the other for the pulse sensor. They work as expected individually but when i combine the code it only displays the pulse readings and doesnt allow me to use the main menu functionality.

```
ISR(TIMER2_COMPA_vect) {                        // triggered when Timer2 counts to 124
  cli();                                      // disable interrupts while we do this
  Signal = analogRead(pulsePin);              // read the Pulse Sensor
  sampleCounter += 2;                         // keep track of the time in mS with this variable
  int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise

  //  find the peak and trough of the pulse wave
  if (Signal < thresh && N > (IBI / 5) * 3) { // avoid dichrotic noise by waiting 3/5 of last IBI
    if (Signal < T) {                       // T is the trough
      T = Signal;                         // keep track of lowest point in pulse wave
    }
  }

  if (Signal > thresh && Signal > P) {        // thresh condition helps avoid noise
    P = Signal;                             // P is the peak
  }                                        // keep track of highest point in pulse wave

  //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
  // signal surges up in value every time there is a pulse
  if (N > 250) {                                  // avoid high frequency noise
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3) ) {
      Pulse = true;                               // set the Pulse flag when we think there is a pulse
      IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
      lastBeatTime = sampleCounter;               // keep track of time for next pulse

      if (secondBeat) {                      // if this is the second beat, if secondBeat == TRUE
        secondBeat = false;                  // clear secondBeat flag
        for (int i = 0; i <= 9; i++) {       // seed the running total to get a realisitic BPM at startup
          rate[i] = IBI;
        }
      }

      if (firstBeat) {                       // if it's the first time we found a beat, if firstBeat == TRUE
        firstBeat = false;                   // clear firstBeat flag
        secondBeat = true;                   // set the second beat flag
        sei();                               // enable interrupts again
        return;                              // IBI value is unreliable so discard it
      }

      // keep a running total of the last 10 IBI values
      word runningTotal = 0;                  // clear the runningTotal variable

      for (int i = 0; i <= 8; i++) {          // shift data in the rate array
        rate[i] = rate[i + 1];                // and drop the oldest IBI value
        runningTotal += rate[i];              // add up the 9 oldest IBI values
      }

      rate[9] = IBI;                          // add the latest IBI to the rate array
      runningTotal += rate[9];                // add the latest IBI to runningTotal
      runningTotal /= 10;                     // average the last 10 IBI values
      BPM = 60000 / runningTotal;             // how many beats can fit into a minute? that's BPM!
      QS = true;                              // set Quantified Self flag
  // QS FLAG IS NOT CLEARED INSIDE THIS ISR
    }
  }

  if (Signal < thresh && Pulse == true) {  // when the values are going down, the beat is over
    Pulse = false;                         // reset the Pulse flag so we can do it again
    amp = P - T;                           // get amplitude of the pulse wave
    thresh = amp / 2 + T;                  // set thresh at 50% of the amplitude
    P = thresh;                            // reset these for next time
    T = thresh;
  }

  if (N > 2500) {                          // if 2.5 seconds go by without a beat
    thresh = 512;                          // set thresh default
    P = 512;                               // set P default
    T = 512;                               // set T default
    lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date
    firstBeat = true;                      // set these to avoid noise
    secondBeat = false;                    // when we get the heartbeat back
  }
  Temp = Thermistor(analogRead(tempPin));
  Sweat = analogRead(moisture);

  sei();                                   // enable interrupts when youre done!
}

```

I think the problem is with the actual header file. When the IRemote is initialised, it calls sei() which then turns on the global interrupts.

Is there a way to solve this issue? I was thinking about something along the lines of each interrupt should be unique and shouldnt be dependent on the other, and is there a way to tell the compiler about a hierarchy of interrupts.

Thanks in advance.

# Answer
1. ISR should be as short as possible. Set flag and let the main program to handle it.
2. Global interrupt flag is handled automatically (on AVR platform), so you don't have to call `cli()`.
3. Enabling interrupts in ISR handler might cause more problem than you can even imagine. Usual one is stack overflow caused by going deeper and deeper by another ISRs (or the same one, if it's longer than ISR period).
> 1 votes

---
Tags: arduino-mega
---


title: Arduino motor shield

text:
# Question
Title: Arduino motor shield
I'm making a soccer car with arduino. And I have this undocumented motor control shield. So I don't know how to program it. I've tried to code it as if it be an H bridge, but is not working. Someone know which are the pins that I have to use? The plate is from DK Electronics, and says motor control shield for arduino.

Don't know why but the image can't be upload from my phone.

As I can't show more this way I have published on my Twitter account the image, if you can I'll be grateful. Link: https://twitter.com/ricardovaras\_99/status/789249497322889216

This is the code I used guided by some internet articles about the Arduino's original motors control shield.

```
 pinMode(8,OUTPUT);       //Channel A Brake Pin Initialize
 pinMode(9,OUTPUT);       //Channel B Brake Pin Initialize
 pinMode(12,OUTPUT);      //Channel A Direction Pin Initialize
 pinMode(13,OUTPUT);      //Channel B Direction Pin Initialize

```

# Answer
> 1 votes
Judging by the fact that you agree it looks like this, a search reveals it is a knock-off of the Adafruit V1 motor shield.

Their page shows how to connect to it, and has example code and a library.

I don't really want to post a link-only answer, but the alternative would be to parrot the Adafruit page, which isn't really fair to them because this board wasn't even purchased from them.

---
Tags: hardware, arduino-motor-shield
---


# Question
Title: Read BLE Characteristic Value in Arduino Uno
I am trying to build a Smart Led project using Arduino Uno, RGB Led, HM-10 BLE module, and Android device.

I am able to connect HM-10 with my android device and read and write characteristic values using Android BlueDroid stack.

But for this project to work I need to check changes in characteristic value in Arduino and process color value and produce output to light up LED.

I thought I could possibly use AT commands (like AT+Name? AT+POWE? AT+CHAR?) parse their result , but I couldn't find any AT command to read characteristic value. **If anyone know such working AT commands for HM-10, please answer?**

Also, I looked into CurieBLE library from Intel for Arduino. I think the library is to work on an Arduino board which has BLE hardware as a built-in feature. If that's not the case, **please help me how can I communicate Arduino and HM-10 using CurieBLE or any other available library?**

# Answer
> 1 votes
I was able to communicate Arduino UNO and HM-10. Whenever one writes a characteristic on BLE using Android application, the exact bytes are transmitted to **Tx/Rx channel** to Arduino and can be read using **SoftwareSerial** Arduino library.

CurieBLE library works on Genuino/Arduino 101 board which has Intel Curie Module.

# Answer
> 0 votes
I found this site that discusses the HM-10 and they linked to the datasheet which lists all the AT commands. The set/query characteristics AT command is listed as #13 on page 24.

Datasheet link.

"Bluetooth 4.0 with HM-10" tutorial for MIT course "How To Make (almost) Anything"

Hope this helps.

---
Tags: arduino-uno, bluetooth, rgb-led
---


# Question
Title: Where to connect BLK and GRN pins of Openlog board on my Uno?
I have the following SD card reader on the left side from Sparkfun. In the tutorial they have it connected directly into an Arduino Mini, which has BLK and GRN pins\> I would like to connect it to an Arduino UNO. Where do I connect these pins or can I ignore them? Thanks for your help.

# Answer
> 3 votes
If you read the page about the OpenLog board you can see (on the schematic link) what the pins mean:

I've added the labelling on the board in blue. The GRN pin (DTR in the schematic) is actually an input, which resets the chip:

Thus:

* `GRN` should be connected to RESET on your Uno, so that when you reset the Uno, you rest the OpenLog.
* `TXO` (transmit out) on the OpenLog would be connected to serial input on the Uno (ie. digital pin D0 - labelled RX).
* `RXI` (receive input) on the OpenLog would be connected to serial output on the Uno (ie. digital pin D1 - labelled TX).
* You can see that `GND` and `BLK` are both ground pins, and thus should be connected to ground.
* `VCC` (RAW on their schematic) is the voltage input to the 3.3V very-low-dropout voltage regulator MIC5205 on the OpenLog. This will accept input voltages in the range 3.3V to 12V. (The datasheet seems to suggest a maximum of 16V, but it might get rather hot if you did that). Connecting VCC to +5V on the Uno would be satisfactory.

# Answer
> 2 votes
It quite simple and stupid that they named the pins with those name. You simply connect:

BLK \> ground

GRN \> RESET

The weird pin abreviations can cause quite a bit of confusion.

**Extra** links for help.

---
Tags: arduino-uno, pins
---


# Question
Title: Float to integer conversion for control program crashes arduino
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);

    }

```

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

---
Tags: arduino-mega, reset, pid
---


title: Utilizing 3G/4G connection as gps

text:
# Question
Title: Utilizing 3G/4G connection as gps
Is it possible to get GPS data without using a GPS, but instead using the internet provided from a 3G or 4G connection to get GPS data?

Maybe if you used the HTML5 geolocation API somehow?

I have already used a GPS module together with a GSM modem, but i only used the GSM modem for SMS and not potential internet capabilities.

The beneftis from this , besides cost, would be a smaller program, intended for arduino nano, as TInyGPS and TinyGPS++ libraries are already big enough.

So my question really is twofold: 1. Is there any way to utilize the internet connection from GSM modems (besides the obvious SMS/call function)? 2. Is there a way to utilize the internet connection to get GPS data, without using an actual GPS module?

# Answer
You cannot get GPS data without getting GPS data. That's like wanting to get milk from a cow without using a cow.

Some GSM modem modules also include a GPS chip. If yours does you can use that. If not then the closest you can get is:

* Country (or maybe city) the IP address is registered in
* Cell ID and location of the tower you are communicating with

Both of those are only very rough "somewhere within this square few miles" or "somewhere in this country" kind of data. Any more than that and you need GPS.

Mobile phones augment the GPS / Cell data with WiFi data by matching BSSIDs with an online database (within Google etc) to get rough location information.
> 2 votes

---
Tags: gsm, gps, tinygps
---


# Question
Title: Use interrupts with analog pins in arduino or another possible solution?
I have a very simple circuit, but my program is some what complicated.

Here is the circuit diagram:

Here is the code:

```
/*
  01 - GND -------- GND
  02 - +5V -------- 5V
  03 - V0  -------- Potentiometer Middle
  04 - Reset ------ 9
  05 - Read/Write - GND
  06 - Enable ----- 8
  07 - Data0 ------ NC
  08 - Data1 ------ NC
  09 - Data2 ------ NC
  10 - Data3 ------ NC
  11 - Data4 ------ 10
  12 - Data5 ------ 11
  13 - Data6 ------ 12
  14 - Data7 ------ 13
  15 - +LCD ------- 5V
  16 - -LCD ------- GND
*/

//include LCD library
#include <LiquidCrystal.h>

//Initialize an LCD object
/*Pins should be mentioned in this order:
  Reset
  Enable
  Data4
  Data5
  Data6
  Data7
*/
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int onTimePin = A0;
int onTime = 0;
int offTimePin = A1;
int offTime = 0;
int ledPin = 13;

void setup()
{

  pinMode(onTimePin, INPUT);
  pinMode(offTimePin, INPUT);

  pinMode(ledPin, OUTPUT);

  //Begin the LCD interface
  lcd.begin(16, 2);

  lcd.print("ON  TIME : ");
  lcd.setCursor(0, 2);
  lcd.print("OFF TIME : ");

}

void loop()
{
  onTime = map(analogRead(onTimePin), 0, 1023, 1, 3);
  lcd.setCursor(11, 0);
  lcd.print(onTime);

  offTime = map(analogRead(offTimePin), 0, 1023, 1, 9);
  lcd.setCursor(11, 1);
  lcd.print(offTime);

  digitalWrite(ledPin, HIGH);
  delay(onTime * 1000);

  digitalWrite(ledPin, LOW);
  delay(offTime * 1000);
}

```

The above code works. But there is a small problem:

When I turn the potentiometer wiper, there is a delay.

It's obvious because when the loop completes, the changed value of potentiometer is displayed. So, I decided to do the same thing using interrupts. But only digital pins have interrupts.

I would like to know the solution for using interrupts on analog input.

# Answer
Avoid `delay`.

Very simplistic alternative:

```
unsigned long lastLedToggleTime;
unsigned long currentLedToggleInterval;

void loop() {
  ...

  unsigned long now = millis();

  if ( (now - lastLedToggleTime) > currentLedToggleInterval) {
    lastLedToggleTime = now;
    // We need to toggle the LED now.
    if ( digitalRead( ledPin ) == LOW ) {
      // LED was LOW, so we set it HIGH and setup next toggling after onTime.
      digitalWrite(ledPin, HIGH);
      currentLedToggleInterval = (onTime * 1000);
    } else {
      // LED was HIGH, so we set it LOW and setup next toggling after offTime.
      digitalWrite(ledPin, LOW);
      currentLedToggleInterval = (offTime * 1000);
    }
  }
  ...
}

```

Notice that we're dealing with 32 bit *unsigned* integer values here, which is why this code will work even if/when `millis()` rolls over to 0. Specifically, not only will `now - lastLedToggleTime` always return a positive value (because it is cast into the unsigned data type), it will also return the *correct* value due to two's complement representation and modulo arithmetic base 2^32.

Example: Let's just look at an 8 bit value for simplicity:

Say, `lastLedToggleTime` was at the last tick of the 8 bit timer value, i.e. `lastLedToggleTime == 255`. In the next timer tick, `now` will overflow to `0`, so next we have `now` \- `lastLedToggleTime` = 0 - 255 = -255. In two's complement, this value would need (at least) 9 bits to represent (binary: `1 0000 0001`), but because we only have 8 bits of storage, the sign bit (MSB) is just discarded resulting in `0000 0001` binary = 1. We can see that 1 is the correct value for the number of ticks to get from 255 to 0; it's exactly one tick.
> 3 votes

# Answer
You are looking for the bad solution for a simple problem. As Ignacio Vazquez-Abrams puts it, the problem is you using `delay()`. The simplest solution is to manage the timings with `millis()`. See the Blink Without Delay Arduino tutorial.
> 3 votes

---
Tags: lcd, potentiometer
---


# Question
Title: Gnd pins at the power pin strip VS Gnd pin at the IO pin strip
I noticed there are two Gnd pins at the lower pin strip, and another on the upper strip. Is there a difference in their purpose?

# Answer
**In short, all the UNO ground pins are the same.**

They are just there to make your life easier. At the end of the day, GND is GND. There is no technichal difference. Just note that is is sometimes better if you share the 3 GND ports. Overloading a port might damage it. Check the datasheet for current limitations of the pins.

---

**EDIT**

The pins (literal pins of the IC) themselves are also different on the ATmega IC.
> 0 votes

---
Tags: power, pins, voltage-level, voltage-protection
---


# Question
Title: Where can I find the Arduino Mega core code?
I am looking to modify the receiving hardware serial buffer size for the Arduino Mega. To do so I need to redefine it in `HardwareSerial.h` in the core code. However, I can't seem to find a copy of the Arduino Mega core code. A search for `HardwareSerial.h` on my computer returns no results. I am using Windows 10.

# Answer
> 0 votes
Arduino Mega is part of the Arduino AVR Boards core. The location of that core depends on whether you are using the core version included with the Arduino IDE or have updated the core version using Boards Manager(in which case there will be multiple copies of the core installed on your computer but only the updated version will be used). The easiest way to find it is:

1. Tools \> Board \> Arduino/Genuino Mega or Mega 2560
2. File \> Examples \> EEPROM \> eeprom\_clear
3. Sketch \> Show Sketch Folder
4. Move up folder levels until you reach the `avr` folder.
5. If there is a version number folder in the `avr` folder then open that folder.
6. HardwareSerial.h and the rest of the core files are located in `cores/arduino`.

Remember that you will need to redo any changes to the core after any Arduino IDE and/or Arduino AVR Boards updates.

---
Tags: arduino-mega, core-libraries
---


# Question
Title: Serial communication between NodeMCU and Arduino doesn't work when I try to use the DC jack or Vin
I have a unidirectional communication from NodeMCU (ESP8266) -\> Arduino UNO. The communication works when I power both the devices to my computer. Note that since it is from NodeMCU to Arduino only, I don't use a voltage regulator. However, when I use a battery supply 9V and connect to DC jack or 9V battery, the serial communication doesn't work. I tried even with the voltage regulator.

It is mentioned that I use something between 9V-12V in the spec. Is it not working because 3.3V/5v from NodeMCU is not sufficient? How do I fix this problem?

1. Currently for the voltage regulator "high", I am supplying 5V from Arduino. Should I provide another supply to pass 9v?
2. Does it power on if I provide 5V to DC jack or Vin?

# Answer
9V "transistor" (PP3) batteries are very weak. They barely provide enough current to power the Arduino, let alone a power hungry device like an ESP8266.

You're basically trying to tow a caravan with a skateboard.
> 1 votes

---
Tags: arduino-uno, esp8266, nodemcu
---


title: ADC port manipulation

text:
# Question
Title: ADC port manipulation
I was modifying this ADC Touch implementation, namely switching *analogRead* and *pinMode* to what I thought would be port manipulation equivalents.

I get very different readings (better and more stable in my case).

So, what I think is equivalent is actually quite different. Can someone point the differences to me?

Original:

```
    pinMode(ADCChannel, INPUT_PULLUP);

    ADMUX |=   0b11111;
    ADCSRA |= (1<<ADSC); //start conversion
    while(!(ADCSRA & (1<<ADIF))); //wait for conversion to finish
    ADCSRA |= (1<<ADIF); //reset the flag

    pinMode(ADCChannel, INPUT);
    _value += analogRead(ADCChannel);

```

Modified:

```
    DDRC &= ~(1 << ADCChannel);
    PORTC |= (1 << ADCChannel);

    ADMUX |=   0b11111;
    ADCSRA |= (1<<ADSC); //start conversion
    while(!(ADCSRA & (1<<ADIF))); //wait for conversion to finish
    ADCSRA |= (1<<ADIF); //reset the flag

    DDRC &= ~(1 << ADCChannel);
    _value += analogRead(ADCChannel);

```

# Answer
> 2 votes
Your modified code doesn't disable the pullup on the pin.

```
PORTC &= ~_BV(ADCChannel);

```

---
Tags: analogread, adc, port-mapping
---


title: Single pin as input and output

text:
# Question
Title: Single pin as input and output
Is there a way to set an Arduino pin as being both an input, and an output?

I was looking at tristates, I'm not sure if that is related, or if there is some other method.

Perhaps I can try switching states rapidly. on one pin. I'm just not familiar with how to do it, and I don't see anything about it on the Arduino site.

This is a function of other microcontrollers, such as PICs, but I'm not sure about AVRs and Arduino types.

# Answer
> 2 votes
The source code for the 1-Wire protocol is a great place to start when learning how to use a single pin for both input and output.

See also chap. 18. I/O-Ports in the ATmega328p datasheet.

Cheers!

# Answer
> 2 votes
A tri-state pin is not both an input and an output, rather each pin can be in 1 of 3 states (High, Low, High Impedance). These are typically used on a bus, where many similar devices are connected.

AFAIK the Arduino does not support tri-state, but it is possible to implement a bus. This was done by using open collector/drain devices with a resistor pull-up.

This was a common method of implementing computer busses (more than 40 years ago with RTL logic), but suffers from slow speed, and low fan-out, due to capacitance.

It is still used for low speed short busses such as I²C and 1-wire.

In practice all devices are set as Input. When a device wants to communicate it is configured as Output.

---
Tags: pins
---


# Question
Title: Pointer to Hardware Differences Documentation For Arduino Boards?
I hope this question isn't overly broad although it is more of a search for consolidated information.

BACKGROUND:

I am new to the Arduino universe and am drawn in by the open hardware concept. After years of doing electronics projects with PICs, I have tired of iterative hardware prototyping and DIY printed circuit construction for small one-off projects. The lure of buying off-the-shelf hardware and doing minimal wiring on protoboards / shields is a powerful concept that I welcome.

The availability of the hardware from multiple sources (and it seems multiple designers) does present a small problem I have discovered. There appear to be small but important differences between Arduino boards from multiple sources.

As an example, I have found that the hardware PWM isn't always the same from one Arduino Board design to another. I find that the arduino.cc pages (including the Forums) appear to indicate that hardware PWM runs at about 487 Hz. However, my testing shows that on the Arduino 101, two of the four hardware PWM outputs run at 487 Hz while the other two run at 975 Hz. I did not find such details when researching board choices and comparisons. I am assuming that this difference may also exist on other board designs although I have only Uno, 101, and Mega2560 boards to play with at the moment.

A second example is that for at least the Arduino Uno and Arduino 101 board I have, the DC power input jack is 5.5mm/2.1mm, a very common size. However, the Arduino Mega2560 I have (third party) uses a 5.5mm/2.5mm DC input jack -- a standard albeit less common size.

Another difference is the well known differences in (TTL) RS232 port interface chips used. At least these are generally made known and documented so that you can plan in advance for differences that may or may not affect you.

Finally, I have found that on the Arduino 101, plugging in or unplugging (or turning on or off) DC power at the DC input jack (or Vin pin) forces a reboot of the Curie module on the board. I think this is caused by the use of the power management chip and power switching circuitry on the board. The Mega2560 does not show this reboot behavior whenever DC power is changed. (This reboot happens even if the USB source remains connected at all times.)

These sorts of minor differences can affect the choice of board one makes for a given project -- especially, if you develop an application on one board and plan to deploy it on another. (Example: develop on a Mega2560 yet intend on deploying on a Uno later to save cost.)

QUESTIONS:

1) Has anyone come across a Website / page that details many of the minor design differences between Arduino boards? \[Edit\] I should have used the word *designs* rather than boards in this question. I realize each vendor may have tweaks to a board but was more interested in detailed differences in the "official" design. Things like above would be interesting to know -- does the board reboot on application of DC input power? Are all PWMs running at the same default frequency, etc?

2) Are there any Web resources that might at least list other "oddities" with the different board choices? (i.e. PWMs at frequencies other than 487 Hz)?

Any pointers would be much appreciated.

# Answer
You may find this helpful: PTD0001 Arduino Comparison Rev 0 \- PDF - 245 KB.

Screenshot of above:

Credit: Payne Technologies Limited

That compares *some* models in a way you might find useful.

---

> I have found that the hardware PWM isn't always the same from one Arduino Board design to another

The PWM frequencies can be changed over quite a wide range. I have a page about timers which describes a lot of their features.

According to the Arduino reference page about analogWrite:

> The frequency of the PWM signal on most pins is approximately 490 Hz. On the Uno and similar boards, pins 5 and 6 have a frequency of approximately 980 Hz. Pins 3 and 11 on the Leonardo also run at 980 Hz.

By changing the hardware register you can change those frequencies. The frequency of 980 Hz is because of the compromise needed to get an approximate 1 ms interrupt for use by the `millis()` function:

```
16e6 / 64 / 256 = 976.5625 Hz

```

In other words the clock speed of 16 MHz is prescaled by 64 and then counted to 256, giving that frequency.

Note that this is *almost* 1 ms. The code behind `millis()` and `micros()` functions compensates for that so that you get a reasonably accurate result.

By changing the prescaler, and "count to" point you can get lots of other frequencies. However if you do that to Timer 0 on the Uno (and similar boards) then you will throw out the calculations for the `millis()` and `micros()` functions (you can compensate for that, of course).

---

This only partly answers your question, but hopefully will provide a nudge in a useful direction.
> 2 votes

---
Tags: arduino-uno, arduino-mega, hardware
---