Showing posts with label ArduinoIDE. Show all posts
Showing posts with label ArduinoIDE. Show all posts

Friday, June 19, 2015

ESP8266 - Arduino IDE v1.6.4 Portable installation Guide



As been asked so many times in the latest days about, please find below a quick install guide that might help you to have a smooth and easy installation:




Arduino IDE 1.6.4 Portable - Blinky test:




Detailed instructions:

1. Download and install Arduino IDE 1.6.4  from http://www.arduino.cc/en/Main/Software  

    In a Windows 7/64 environment I preffer to use the ZIP file:
     http://arduino.cc/download.php?f=/arduino-1.6.4-windows.zip
     and install it manually, in a more compact and portable manner.





  • Create a New Folder where do you want your Arduino IDE installation to be (ex: D:\ESP8266_Arduino)







  • Delete arduino-1.6.4-windows.zip to free your space
  • Inside the new "arduino-1.6.4" subfolder create a New Folder called "Portable"  


In this way you can avoid the way Arduino is installing files all over the place on your system. All your Arduino IDE v 1.6.4 files will be located only under the new created "arduino-1.6.4" folder. And yes, your drive can be in this case a Stick/SD Card or external HDD/SSD Drive so you can take your Arduino IDE and your projects everywhere, just ready for coding!



2.  Start the new installed Arduino IDE.
  •  Go to File 
  •  Preferences -  in  Preferences window go to "additional boards manager URL's" where you need to paste the following link:
     https://adafruit.github.io/arduino-board-index/package_adafruit_index.json



  •  Click OK button.
  • Go to Tools 
  •  Boards  - > Boards manager, in the Boards manager window select "contributed" from the TYPE drop 
  •  Select ESP8266 by ESP8266 community forum and version 1.6.2 


  •  Press Install. 

    Installation process can take a while, so please be patient! A cup of tea/coffee might work here :)








4. Restart IDE

5. Select your board as ADAFRUIT HUZZAH ESP8266 or GenericESP8266 Module. For CBDBv2 EVO use provided config file or GenericESP8266.

6. Select CPU frequency: 80Mhz

7. Select your Serial port and upload speed. Looks like it's working upto 921600 but quite unstable. Keep the usual 115200 baud for more solid upload results.




   You are ready for your first ESP8266 Program written in Arduino IDE :)








Tuesday, June 16, 2015

Arduino IDE - Nasty bug in dtostrf() ESP8266 STDLIB function - FIXED!



    Working last days on the driver for MAX7219 8 digit display module I found that dtostrf() ESP8266 STDLIB function is not working properly for values containing "0"'s after dot, like: 1.0256,1.00256, etc.

With the quick written test code from below and  the collaboration of the great guys from Arduino.cc Forum was able to confirm that it is a nasty BUG and is affecting ESP8266 libraries only, on Arduino (AVR) boards results confirmed from different sources as been OK.


TEST CODE:


void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
}

void print_float(int no, float fVal, String sVal )
{
char charVal[12];          //temporarily holds data from vals 
String stringVal = "";     //data on buff is copied to this string

dtostrf(fVal, 8, 4, charVal);  
//4 is mininum width, 3 is precision; float value is copied onto buff

stringVal = charVal;
int strl = stringVal.length()-1;

Serial.print(no);  //just a order number
//the number represented as string for reference 
Serial.print(". Expected value :"); Serial.print(sVal); 
//display lenght of the obtained string after conversion  
Serial.print(" - String Length: ");Serial.print(strl);
//display the value as stored in stringVal 
Serial.print(" - Conversion value in stringVal :");
Serial.println(stringVal); 
}

void loop() {
   print_float(1,1.256,"1.2560");   //No 1
   print_float(2,1.0256,"1.0256");  //No 2
   print_float(3,1.00256,"1.0026"); //No 3
   Serial.println();  
   delay(5000);        // delay in between reads for stability
}



WRONG RESULT - ESP8266 build

1. Expected value :1.2560 - String Length: 5 - Conversion value in stringVal: 1.2560
2. Expected value :1.0256 - String Length: 4 - Conversion value in stringVal: 1.256
3. Expected value :1.0026 - String Length: 3 - Conversion value in stringVal: 1.26
 
 
 
TEST PASSED RESULT - Arduino (AVR) build:

1. Expected value :1.2560 - String Length: 7 - Conversion value in stringVal: 1.2560
2. Expected value :1.0256 - String Length: 7 - Conversion value in stringVal: 1.0256
3. Expected value :1.0026 - String Length: 7 - Conversion value in stringVal: 1.0026
 


For ESP8266 Arduino IDE package the "dtostrf()" function is hidding in "core_esp8266_noniso.c" and is called by "#include<stdlib_noniso.h>"


Original code below:

char * dtostrf(double number, signed char width, unsigned char prec, char *s) 
{

    if(isnan(number)) {
        strcpy(s, "nan");
        return s;
    }
    if(isinf(number)) {
        strcpy(s, "inf");
        return s;
    }

    if(number > 4294967040.0 || number < -4294967040.0) {
        strcpy(s, "ovf");
        return s;
    }
    char* out = s;
    // Handle negative numbers
    if(number < 0.0) {
        *out = '-';
        ++out;
        number = -number;
    }

    // Round correctly so that print(1.999, 2) prints as "2.00"
    double rounding = 0.5;
    for(uint8_t i = 0; i < prec; ++i)
        rounding /= 10.0;

    number += rounding;

    // Extract the integer part of the number and print it
    unsigned long int_part = (unsigned long) number;
    double remainder = number - (double) int_part;
    out += sprintf(out, "%d", int_part);

    // Print the decimal point, but only if there are digits beyond
    if(prec > 0) {
        *out = '.';
        ++out;
    }

    while(prec-- > 0) {
        remainder *= 10.0;
    }
    sprintf(out, "%d", (int) remainder);

    return s;
}


   Going step-by-step thru the code is quite easy to find out that the remainder part is moved into integer, but on the iteration process the leading zeroes are not added into the buffer.


  The fix is simple, changing the remainder add section in a way to properly add the "0"'s to the buffer  until the remainder part become non-zero:

while(prec-- > 0) {
        remainder *= 10.0;
        if((int)remainder == 0){
                *out = '0';
                 ++out;
        }
    }


The fixed dtostrf() code below:


char * dtostrf(double number, signed char width, unsigned char prec, char *s)
 {

    if(isnan(number)) {
        strcpy(s, "nan");
        return s;
    }
    if(isinf(number)) {
        strcpy(s, "inf");
        return s;
    }

    if(number > 4294967040.0 || number < -4294967040.0) {
        strcpy(s, "ovf");
        return s;
    }
    char* out = s;
    // Handle negative numbers
    if(number < 0.0) {
        *out = '-';
        ++out;
        number = -number;
    }

    // Round correctly so that print(1.999, 2) prints as "2.00"
    double rounding = 0.5;
    for(uint8_t i = 0; i < prec; ++i)
        rounding /= 10.0;

    number += rounding;

    // Extract the integer part of the number and print it
    unsigned long int_part = (unsigned long) number;
    double remainder = number - (double) int_part;
    out += sprintf(out, "%d", int_part);

    // Print the decimal point, but only if there are digits beyond
    if(prec > 0) {
        *out = '.';
        ++out;
    }

    while(prec-- > 0) {
        remainder *= 10.0;
        if((int)remainder == 0){
                *out = '0';
                 ++out;
        }
    }
    sprintf(out, "%d", (int) remainder);

    return s;
}


To fix your own ESP8266 Arduino IDE lib, just replace the old "dtostrf()" function  in "core_esp8266_noniso.c" with the code above.

I have posted it also on esp8266.com, maybe somebody will put the fix also in mainstream code.

All the credits for the bugfix will go this time to "Delta_G" from Arduino.cc forum, who was the quickest in posting a solution. They are also other solutions, including mine, but this one it's the most elegant until now.

 Please feel free to add yours if you want :)





Monday, June 15, 2015

Arduino IDE - MAX7219 - 8 Digit Display Driver







   As you know from my previous Article I got recently some nice MAX7219 8 Digit Display Modules.

   Had a lot fun fun with them, looks a nice and stable solution so I'm thinking to use them as Display for one of my future projects.

   Meanwhile I was also playing with ESP8266 CBDBv2 EVO and Arduino IDE and because it looks like the latest 1.6.4 version  it's becoming more stable and usable than previous releases I will give it a try for MAX7219 Driver implementation.

   I still consider ESP8266 + NodeMCU LUA interpreter as the best environment for Learning/Drivers Developpment or even small projects, offering you a great flexibility that a Interpreter can give you   but it's obviously that for bigger projects you need something else, so let's give Arduino IDE a try.



What we will need:


 I will not insist to much on the Arduino IDE install process, it is a quite trivial process. If anybody wants more details about please feel free to ask.


MAX 7219 - 8 digit display driver connections




Wire        MAX7219     ESP8266

Green      +5Vcc
Blue        GND               GND
Yellow     DIN                 13
White      CS                  12
Orange    CLK                14




   MAX7219 Driver  Implementation

    For details about MAX Timing Diagram,  Registers, Initialisation, etc please take a look at the detailed description from the previous MAX7219 article.


1.  Init

int INTENSITYMIN = 0; // minimum brightness, valid range [0,15]
int INTENSITYMAX = 1; // maximum brightness, valid range [0,15]

int DIN_PIN = 13;      // data in pin
int CS_PIN = 12;       // load (CS) pin
int CLK_PIN = 14;      // clock pin
int dly = 50;          // delay in us
int adc=0;             // read ADC
int spr=32;            // number of readings
int offset=5;          // input offset

float nr = 1.0054;     // number to be displayed

// MAX7219 registers
byte MAXREG_DECODEMODE = 0x09;
byte MAXREG_INTENSITY  = 0x0a;
byte MAXREG_SCANLIMIT  = 0x0b;
byte MAXREG_SHUTDOWN   = 0x0c;
byte MAXREG_DISPTEST   = 0x0f;



2. Write serialised data

void putByte(byte data)
{
  byte i = 8;
  byte mask;
  while (i > 0)
  {
    mask = 0x01 << (i - 1);        // apply bitmask
    digitalWrite( CLK_PIN, LOW);   // CLK
      delayMicroseconds(dly);
    if (data & mask)               // select bit
    {  digitalWrite(DIN_PIN, HIGH); // send 1
      delayMicroseconds(dly);
    }else{
      digitalWrite(DIN_PIN, LOW);  // send 0
      delayMicroseconds(dly);}
    digitalWrite(CLK_PIN, HIGH);   // CLK
      delayMicroseconds(dly);
    --i;                           // move to next bit
  }
}


3. Set Register

void setRegistry(byte reg, byte value)
{
  digitalWrite(CS_PIN, LOW);
  delayMicroseconds(dly);
  putByte(reg);   // specify register
  putByte(value); // send data

  digitalWrite(CS_PIN, LOW);
  delayMicroseconds(dly); 
  digitalWrite(CS_PIN, HIGH);
}


 

4. Convert anf Print float value in  xxxx.xxx format

void print_LED(float fVal, int w, int p)
{
  int d = 1;
  int ch = 1;
  int n = 0;
  int nr_size = 0;
  char charVal[11];               //temporarily holds data from vals
  String stringVal = "";     //data on buff is copied to this string
 
  //dtostrf(fVal, w, p, charVal);  //4 is mininum width, 3 is precision; 

                           //NOT WORKING FOR Values SMALLER THAT 0.01 !!
  // stringVal = charVal;
  // created a new function below for converting properly a pozitive xxxx.xxx float to string



  stringVal=ftos(fVal,3);
 
  int strl = stringVal.length()-1; 
  for (int i=0;i<strl+1;i++)
  { charVal[i]=stringVal[i]; }
 
    Serial.print("Length: ");Serial.println(strl); //display string
    Serial.println(stringVal);
  //convert charVal[] to LED Display string
  for(int i=0;i<strl+1;i++)
  {
    if ((charVal[i] == '.') && (d==1))
    {
    stringVal=charVal[i];
    n = 0;
    n = (n * 10) + (charVal[i-1] - 48);
    setRegistry(strl-i+1, 128+n);
    d = 0;   
    }
    else  {          
        stringVal=charVal[i];
        Serial.print("d: ");Serial.print(d); //display string
        Serial.print("  - Increment: ");Serial.print(i); //display string
        Serial.print(" - INT: ");Serial.println(charVal[i]); //display string
        n=0;
        n = (n * 10) + (charVal[i] - 48);
        int pos = i;
        if (d==0) { pos = i-1; }
        setRegistry(strl-pos,n);
    } 
  }
}




5. Convert float value to a string 
 
 String ftos(float fVal, int prec)
{
  int mlt=10;
  String snr; 
  String dp;
  int iprt,dprt;
 
  iprt = int(fVal);

   // Round fVal for proper prec printing - correctly so that print(1.999, 2) prints as "2.00"
   double rnd = 0.5;
   for(uint8_t i = 0; i < prec; ++i)
        rnd /= 10.0;
        mlt *= 100;
    fVal += rnd;
   

 // Check and count "0"'s proper after ZERO (0.00xx) number display
  dprt = 1000*(fVal-iprt); 
  if (dprt < 10)
  {
    dp = "00" + String(dprt);
  }else
        if (dprt < 100)
        {
          dp = "0" + String(dprt);
        }else {dp = dprt;}

  snr = String(iprt) +"."+String(dp); 

  //Serial.println("");
  //Serial.print("MLT: ");Serial.println(mlt);  
  //Serial.println("");
  //Serial.print("DEC Part: ");Serial.println(dprt);  
  //Serial.println("");
  //Serial.print("Int Part: ");Serial.println(iprt);             
  //Serial.print(" . "); 
  //Serial.print("DP: "); Serial.print(dp);

  return snr;
}




5. Create a  Display 'ZERO' init stage

void zero_lcd()
{
 for (int i=1;i<9;i++)
 {
  setRegistry(i, 0);
    delayMicroseconds(100); 
 }
}



6.  MAX7219 Initialisation  

void init_MAX7219()
{
  // select allocated I/O pins
  pinMode(DIN_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(CS_PIN, OUTPUT);

  // initialization of the MAX7219
  setRegistry(MAXREG_SCANLIMIT, 0x07);
    delayMicroseconds(dly);
  setRegistry(MAXREG_DECODEMODE, 0xFF);  // full decode mode BCD 7 Seg Display
    delayMicroseconds(dly);
  setRegistry(MAXREG_SHUTDOWN, 0x01);    // shutdown mode OFF
    delayMicroseconds(dly);
  setRegistry(MAXREG_DISPTEST, 0x00);    // no test
    delayMicroseconds(dly);
  setRegistry(MAXREG_INTENSITY, 0);
    delayMicroseconds(dly);
  zero_lcd();
}


 

7. Test Display Driver - Read live ADC values and print them


float read_adc()
{
  adc = 0;
  for (int i=0;i<spr;i++)
  {
   adc += analogRead(0);
  } 
  nr = (float)(adc/spr-offset)*0.0009657;
 return nr;
}


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


void loop ()
{
  nr = read_adc();

  Serial.println((float)adc/spr);
  print_LED(nr,4,3);
 
  delay(5000);
  }