Thursday, April 30, 2015

Windows 10 + Arduino Partnership

Arduino Partnership

Arduino Certified” Windows 10 enables developers to make devices that combine the hardware-driving capability of Arduino with the software capabilities of Windows. An example might be a security camera. One could build a camera using Arduino to power the motor controls to tilt/turn the camera and using Universal Windows Platform one can create great UI, connect the camera to the cloud, process the image for motion detection and add facial/voice recognition. The work we have done on Windows 10 is the bridge between the Universal Windows Platform and Arduino hardware. The initial release includes two key capabilities:

  • Windows Virtual Shield for Arduino enables developers to tap into the incredible power of Windows 10 devices through wireless protocols. A Lumia 530 contains well over $200-worth of Arduino shield sensors and capabilities, and we’ve made it easy to access all of those sensors and capabilities from an Arduino as if they were standard hardware shields. Imagine being able to create an Arduino project that includes GPS, Web connectivity/parsing, touch display, speech technologies and more. We’re particularly fond of the picture the weather project we’ve created that lets you bring your children’s drawings to life.
  • With Windows Remote Arduino we’re enabling developers to extend their Universal Windows Application with Arduino commands that execute on a wirelessly-connected Arduino device. It combines the power of Windows 10 device features such as image processing, speech recognition, website parsing, cameras and advanced audio pipelines with the power of physical world interactivity through Arduino. Take a look at our Basic Windows Remote Arduino project to learn how to leverage this technology in your own projects. 

Source: Windows Blog - Microsoft brings Windows 10 to Makers

Wednesday, April 29, 2015

Arduino Due + ESP8266 - to Join AP

Arduino Due connect with ESP8266 work in CWMODE=1, to join AP shared by mobile phone.


Connection between Due and ESP8266, refer to last post "Connect ESP8266 (WiFi module) to Arduino Due".


Due8266.ino
/*
Arduino Due - ESP 8266 WiFi Module
Serial (Tx/Rx) communicate to PC via USB
Serial3 (Tx3/Rx3) connect to ESP8266
Tx3 - ESP8266 Rx
Rx3 - ESP8266 Tx
pin 53 - ESP8266 CH_PD (Always High)
*/
#define ESP8266 Serial3
String SSID = "TestAP";
String PASSWORD = "12345678";

int LED = 13;

//always high
int CH_PD_8266 = 53;

boolean FAIL_8266 = false;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(CH_PD_8266, OUTPUT);
  digitalWrite(CH_PD_8266, LOW);
  
  digitalWrite(LED, LOW);
  delay(500);
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);
  delay(500);
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);
  delay(500);
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);

  digitalWrite(CH_PD_8266, HIGH);
  delay(1000);

  do{
    Serial.begin(9600);
    ESP8266.begin(9600);
  
    //Wait Serial Monitor to start
    while(!Serial);
    Serial.println("--- Start ---");

    ESP8266.println("AT+RST");
    delay(1000);
    if(ESP8266.find("ready"))
    {
      Serial.println("Module is ready");
      ESP8266.println("AT+CWMODE=1");
      delay(2000);
      
      //Quit existing AP, for demo
      Serial.println("Quit AP");
      ESP8266.println("AT+CWQAP");
      delay(1000);
      
      clearESP8266SerialBuffer();
      if(cwJoinAP())
      {
        Serial.println("CWJAP Success");
        FAIL_8266 = false;
        
        delay(3000);
        cwGetIP();
      }else{
        Serial.println("CWJAP Fail");
        delay(500);
        FAIL_8266 = true;
      }
    }else{
      Serial.println("Module have no response.");
      delay(500);
      FAIL_8266 = true;
    }
  }while(FAIL_8266);
  
  digitalWrite(LED, HIGH);
}

void loop() {

}

boolean waitOKfromESP8266(int timeout)
{
  do{
    Serial.println("wait OK...");
    delay(1000);
    if(ESP8266.find("OK"))
    {
      return true;
    }

  }while((timeout--)>0);
  return false;
}

boolean cwJoinAP()
{
  String cmd="AT+CWJAP=\"" + SSID + "\",\"" + PASSWORD + "\"";
  ESP8266.println(cmd);
  return waitOKfromESP8266(10);
}

//show IP address on Serial Monitor
void cwGetIP()
{
  clearESP8266SerialBuffer();
  ESP8266.println("AT+CIFSR");
  delay(1000);
  
  while (ESP8266.available() > 0) {
    char a = ESP8266.read();
    Serial.write(a);
  }
}

void clearESP8266SerialBuffer()
{
  Serial.println("= clearESP8266SerialBuffer() =");
  while (ESP8266.available() > 0) {
    char a = ESP8266.read();
    Serial.write(a);
  }
  Serial.println("==============================");
}



Tuesday, April 28, 2015

Connect ESP8266 (WiFi module) to Arduino Due

Just to prove the connection between Arduino Due (TX3/RX3) and ESP8266 WiFi module, electrically and logically. Because both Arduino Due and ESP8266 work on 3.3V, so no voltage converter is needed.

ESP8266 GND - Due GND
ESP8266 VCC - Due 3.3V
ESP8266 TX - Due RX3
ESP8266 RX - Due TX3
ESP8266 CH_PD - Due pin 53 (always HIGH)

The test program on Arduino Due simple redirect the received data from RX to TX3, and from RX3 to TX. Such that we can use Serial Monitor of Arduino IDE (TX/RX) to send command to ESP8266 (TX3/RX3). It act as a USB-Serial cable functionally. Pin 53 always High, such that the ESP8266 always NOT Power Down.



int LED = 13;
boolean LEDst = false;

//always high
int CH_PD_8266 = 53;

void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LEDst);
  pinMode(CH_PD_8266, OUTPUT);
  digitalWrite(CH_PD_8266, HIGH);
}

void loop() {
  while (Serial.available() > 0) {
    char a = Serial.read();
    Serial3.write(a);
  }
  
}

void serialEvent3() {
  while (Serial3.available() > 0) {
    char a = Serial3.read();
    Serial.write(a);
    ToggleLED();
  }
}

void ToggleLED(){
  digitalWrite(LED, LEDst = !LEDst);
}




Next:
- Arduino Due + ESP8266 - to Join AP

Sunday, April 26, 2015

Simple Compass - Arduino Nano + GY-271(HMC5883L) + mini-OLED

Use Arduino Nano + GY-271 Digital Compass Module (with HMC5883L) + 0.96" I2C mini-OLED to implement a simple compass.


For HMC5883L library with calibration, refer LAST POST.
For u8glib library used on 0.96" I2C mini OLED, refer Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library.
Connection between Arduino Nano, GY-271 and the mini OLED via I2C, refer to Arduino Nano + GY-271 (Digital Compass module) + OLED.


Nano_Compass.ino
/*
http://arduino-er.blogspot.com/

For HMC5883L_Header_Arduino_Auto_calibration library
ref: http://hobbylogs.me.pn/?p=17

For u8glib Universal Graphics Library for 8 Bit Embedded Systems
ref: https://code.google.com/p/u8glib/
*/

#include "U8glib.h"
#include <Wire.h>
#include "compass.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#define Task_t 10          // Task Time in milli seconds

int dt=0;
unsigned long t;
// Main code -----------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  // Serial.print("Setting up I2C ........\n");
  Wire.begin();
  compass_x_offset = -48.23;  //122.17;
  compass_y_offset = 284.69;  //230.08;
  compass_z_offset = 59.87;  //389.85;
  compass_x_gainError = 1.07;  //1.12;
  compass_y_gainError = 1.09;  //1.13;
  compass_z_gainError = 1.01;  //1.03;
  
  compass_init(2);
  //compass_debug = 1;
  //compass_offset_calibration(3);

}

void loop(){
  
  t = millis();
 
  float load;
 
  compass_scalled_reading();
  
  Serial.print("x = ");
  Serial.println(compass_x_scalled);
  Serial.print("y = ");
  Serial.println(compass_y_scalled);
  Serial.print("z = ");
  Serial.println(compass_z_scalled);
  
  compass_heading();
  Serial.print ("Heading angle = ");
  Serial.print (bearing);
  Serial.println(" Degree");
  
  dt = millis()-t;
  load = (float)dt/(Task_t/100);
  Serial.print ("Load on processor = ");
  Serial.print(load);
  Serial.println("%");
  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );

  delay(100);
}

void draw(void) {
  static int armLength = 20;
  static int cx = 64;
  static int cy = 20;
  int armX, armY;
  
  //convert degree to radian
  float bearingRad = bearing/57.2957795;
  armX = armLength*cos(bearingRad);
  armY = -armLength*sin(bearingRad);

  u8g.setFont(u8g_font_unifont);
  
  u8g.setPrintPos(0, 60);
  u8g.print("bearing: ");
  u8g.setPrintPos(70, 60);
  u8g.print(bearing);
  
  u8g.drawLine(cx, cy, cx-armX, cy-armY);
  u8g.drawCircle(cx, cy, armLength, U8G_DRAW_ALL);

}

Saturday, April 25, 2015

HMC5883L library with calibration, for Arduino

Last post I read HMC5883L (in GY-271) from Arduino Nano. Then I tried to convert to bearing by calling atan2((double)y, (double)x) * 180/M_PI. The result have very big error without calibration. Finally I found this library HMC5883L Header Arduino With Auto calibration. For detail about the functions read http://hobbylogs.me.pn/?p=17#more-17


Here is modified from Compass_header_example_ver_0_2.ino to display bearing on mini OLED.
/*
For HMC5883L_Header_Arduino_Auto_calibration library
ref: http://hobbylogs.me.pn/?p=17
*/

#include "U8glib.h"
#include <Wire.h>
#include "compass.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#define Task_t 10          // Task Time in milli seconds

int dt=0;
unsigned long t;
// Main code -----------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  // Serial.print("Setting up I2C ........\n");
  Wire.begin();
  compass_x_offset = -48.23;  //122.17;
  compass_y_offset = 284.69;  //230.08;
  compass_z_offset = 59.87;  //389.85;
  compass_x_gainError = 1.07;  //1.12;
  compass_y_gainError = 1.09;  //1.13;
  compass_z_gainError = 1.01;  //1.03;
  
  compass_init(2);
  //compass_debug = 1;
  //compass_offset_calibration(3);

}

// Main loop 
// Main loop -----------------------------------------------------------------
void loop(){
  
  t = millis();
 
  float load;
 
  compass_scalled_reading();
  
  Serial.print("x = ");
  Serial.println(compass_x_scalled);
  Serial.print("y = ");
  Serial.println(compass_y_scalled);
  Serial.print("z = ");
  Serial.println(compass_z_scalled);
  
  compass_heading();
  Serial.print ("Heading angle = ");
  Serial.print (bearing);
  Serial.println(" Degree");
  
  dt = millis()-t;
  load = (float)dt/(Task_t/100);
  Serial.print ("Load on processor = ");
  Serial.print(load);
  Serial.println("%");
  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );

  
  delay(100);
}

void draw(void) {
  u8g.setFont(u8g_font_unifont);

  u8g.setPrintPos(0, 15);
  u8g.print("x: ");
  u8g.setPrintPos(70, 15);
  u8g.print(compass_x_scalled);
  
  u8g.setPrintPos(0, 30);
  u8g.print("y: ");
  u8g.setPrintPos(70, 30);
  u8g.print(compass_y_scalled);
  
  u8g.setPrintPos(0, 45);
  u8g.print("z: ");
  u8g.setPrintPos(70, 45);
  u8g.print(compass_z_scalled);
  
  u8g.setPrintPos(0, 60);
  u8g.print("bearing: ");
  u8g.setPrintPos(70, 60);
  u8g.print(bearing);

}

For compass.cpp and compass.h, refer to https://github.com/helscream/HMC5883L_Header_Arduino_Auto_calibration/tree/master/Core/Compass_header_example_ver_0_2.



Next:
- Simple Compass - Arduino Nano + GY-271(HMC5883L) + mini-OLED

Friday, April 24, 2015

Arduino Nano + GY-271 (Digital Compass module) + OLED

This example show a Arduino Nano, connect with GY-271 Digital Compass module and 0.96" 128x64 OLED via a common I2C bus. GY-271 is a Digital Compass module using HMC5883L, a 3-Axis Digital Compass IC. The reading from GY-271 (x, y, abd z) is display on the OLED. Arduino Nano communicate with GY-271 via I2C bus using Wire library. Arduino Nano communicate with 0.96" 128x64 OLED via the same I2C bus, using u8glib library. I'm not sure is it 100% compatible to use both Wire and u8glib libraries, both share the common I2C bus. Anyway in this example it work.


Connection:
VCC of GY-271, OLED and Arduino Nano connect together.
GND of GY-271, OLED and Arduino Nano connect together.
SCL of GY-271 and OLED connect to A5 of Arduino Nano.
SDA of GY-271 and OLED connect to A4 of Arduino Nano.
DRDY of GY-271 no connection.
(In the following Fritzing drawing, the HMC5883 breakout not exactly my GY-271 module, just to show the connect of SCL and SDA.)


Nano_OLED_Compass.ino
#include "U8glib.h"
#include <Wire.h> //I2C Arduino Library

#define address 0x1E //0011110b, I2C 7bit address of HMC5883

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

int x,y,z; //triple axis data

char bufferX [20];
char bufferY [20];
char bufferZ [20];

void draw(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 20, bufferX);
  u8g.drawStr( 0, 40, bufferY);
  u8g.drawStr( 0, 60, bufferZ);

}

void setup(void) {
  x = 0;
  y = 0;
  z = 0;
  
  Wire.begin();
  
  //Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();

}

void loop(void) {
  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
  
 
 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  sprintf(bufferX, "x : %d", x);
  sprintf(bufferY, "y : %d", y);
  sprintf(bufferZ, "z : %d", z);

  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  delay(100);
}



Then I tried to find the bearing by calling atan2((double)y, (double)x) * 180/M_PI, but get a very big error without calibration. Finally I found a library with auto calibration, read next: HMC5883L library with calibration, for Arduino.

About 3-Axis Digital Compass IC HMC5883L:



- 3-Axis Digital Compass IC HMC5883L
- Application Note – AN226 Honeywell HMC5883L/HMC5983 3-Axis Digital Compass IC Pin Configuration for I2C Communication

Tuesday, April 21, 2015

Arduino Nano: Capture analog input in Timer Interrupt

Last post show a "oscilloscope-like waveform on 0.96" 128X64 I2C OLED with Arduino Nano". But the analog input is captured inside loop(), it's not in fixed timing, and affected by the slow operation of displaying.

To capture analog input in accurate timing, we are going to implement TIMER1 ISR (Interrupt Service Routine) in this example, and call analogRead() to capture analog input inside ISR.


Connecttion between Arduino Nano and OLED, refer to last post.

To understand Arduino Timer and Interrupt, it have a good tutorial HERE.

I2C_OLED_scope.ino
// Display analog input to mini-OLED I2C,
// capture input inside TIMER1 ISR
// http://arduino-er.blogspot.com/

// OLED display: ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const int WIDTH=128;
const int HEIGHT=64;
const int LENGTH=WIDTH;

const int LED = 13;
boolean LEDst = false;

//true: request capture analog input in ISR
//false: stop capture, draw waveform in loop
boolean capture = false;

const int analogInPin = A0;
int analogInValue = 0;

int x;
int y[LENGTH];

/*
    reference: Arduino Timer and Interrupt Tutorial
    http://blog.oscarliang.net/arduino-timer-and-interrupt-tutorial/
    
    For our TIMER1 Interrupt:
    Clock Freq = 16MHz
    no prescale, 1
    16MHz - 0.0625us/cycle
   
    To calculator preload value to generate 1ms(1KHz) 
    (65536 - t) x 0.0625us = 1000us
    t = 65536 - 1000/0.0625 = 49536
    
    To calculator preload value to generate 0.5ms(2KHz)
    (65536 - t) x 0.0625us = 500us
    t = 65536 - 500/0.0625 = 57536

 */
const int TCNT1_PRELOAD = 57536;

void clearY(){
  for(int i=0; i<LENGTH; i++){
    y[i] = -1;
  }
}

void drawY(){
  u8g.drawPixel(0, y[0]);
  for(int i=1; i<LENGTH; i++){
    u8g.drawLine(i-1, y[i-1], i, y[i]);
  }
}

void setup(void) {
  
  pinMode(LED, OUTPUT);
  
  // initialize Timer1
  noInterrupts(); // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = TCNT1_PRELOAD;
  TCCR1B |= (1 << CS10);   // no prescaler
  TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
    
  x = 0;
  clearY();
  capture = true;

  interrupts(); // enable all interrupts  
}

void loop(void) {
  if(!capture){
    
    u8g.firstPage();  
    do {
      drawY();
    } while( u8g.nextPage() );
    
    //start capture another frame
    x = 0;
    clearY();
    capture = true;
  }

  delay(100);

}

ISR(TIMER1_OVF_vect){
  TCNT1 = TCNT1_PRELOAD; // preload timer
  
  if(capture){
    //toggle LED
    digitalWrite(LED, LEDst=!LEDst);
  
    analogInValue = analogRead(analogInPin);
    y[x] = map(analogInValue, 0, 1023, HEIGHT-1, 0);
    
    x++;
    if(x >= WIDTH){
      capture = false;
    }
  }
}

Monday, April 20, 2015

Display waveform on mini OLED with Arduino Nano

Display oscilloscope-like waveform on 0.96" 128X64 I2C OLED with Arduino Nano. Read analog input (A0) and plot the waveform acordingly.



// ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const int WIDTH=128;
const int HEIGHT=64;
const int LENGTH=WIDTH;

const int analogInPin = A0;
int analogInValue = 0;

int x;
int y[LENGTH];

void clearY(){
  for(int i=0; i<LENGTH; i++){
    y[i] = -1;
  }
}

void drawY(){
  u8g.drawPixel(0, y[0]);
  for(int i=1; i<LENGTH; i++){
    if(y[i]!=-1){
      //u8g.drawPixel(i, y[i]);
      u8g.drawLine(i-1, y[i-1], i, y[i]);
    }else{
      break;
    }
  }
}

void setup(void) {
  x = 0;
  clearY();
}

void loop(void) {
  
  analogInValue = analogRead(analogInPin);
  
  y[x] = map(analogInValue, 0, 1023, HEIGHT-1, 0);;

  u8g.firstPage();  
  do {
    drawY();
  } while( u8g.nextPage() );
  
  //delay(10);

  x++;
  if(x >= WIDTH){
    x = 0;
    clearY();
  }
}


This example read analog input inside loop(), it's not in fixed timing, and affected by the slow operation of displaying. To read input in accurate timing, Refer to next post "Capture analog input in Timer Interrupt".

Walking bitmap on 0.96 inch 128X64 I2C OLED x Arduino Nano

Implement walking bitmap on 0.96 inch 128X64 I2C OLED x Arduino Nano V3.0 (ATmega328 5V), using u8glib library.


(Refer to te post "Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library" to install the library to Arduino IDE)

Connect the 0.96 inch 128X64 I2C OLED to Arduino Nano:

GND - GND on Arduino Uno
VCC - 5V on Arduino Uno
SCL - A5 on Arduino Uno
SDA - A4 on Arduino Uno

I2C_OLED_bitmap.ino
// ref u8glib: https://code.google.com/p/u8glib/
// To install u8glib on Arduino IDE: http://goo.gl/j3olBA
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

const uint8_t bm[] PROGMEM = {
  0b00011000,
  0b00111100,
  0b01111110,
  0b11111111,
  0b11111111,
  0b01111110,
  0b00111100,
  0b00011000
};

static int WIDTH=128;
static int HEIGHT=64;

int x, y;

void setup(void) {
  x = 0;
  y = 0;
}

void loop(void) {

  u8g.firstPage();  
  do {
    u8g.drawBitmapP( x, y, 1, 8, bm);
  } while( u8g.nextPage() );
  
  delay(100);

  x += 8;
  if( x >= WIDTH){
    x = 0;
    y += 8;
    if( y >= HEIGHT){
      y = 0;
    }
  }
}


Sunday, April 19, 2015

Hello World 1.3 inch IIC/SPI 128x64 OLED x Arduino, using u8glib library

It's a 1.3"" 128X64 OLED module, I2C/SPI interface (4-wire SPI selected), with SH1106 driver (SSD1306 compatible), 3.3/5V compatible. This post show how to modify from HelloWorld of u8glib library, to make it work. TO download and install u8glib library, refer to last post "Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library". It work on both Arduino Uno with 5V, and Arduino Due with 3.3V.

Connection between the OLED module to Arduino Uno (Arduino Due):
4 wire SPI OLED - Arduino Uno (Due)
GND - GND
VCC - 5V (3.3V for Arduino Due)
D0 - 10
D1 - 9
RST - 13
DC - 11
CS - 12

To make the HelloWorld work with this OLED module, add the following constructor calls:
U8GLIB_SH1106_128X64 u8g(10, 9, 12, 11, 13);

Then modify the code, to make a rotating message:

HelloWorld_SpiOled.ino
/*

  HelloWorld.pde
  
  "Hello World!" example code.
  
  >>> Before compiling: Please remove comment from the constructor of the 
  >>> connected graphics display (see below).
  
  Universal 8bit Graphics Library, http://code.google.com/p/u8glib/
  
  Copyright (c) 2012, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  
*/


#include "U8glib.h"

// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 
// devices with all constructor calls is here: http://code.google.com/p/u8glib/wiki/device
//U8GLIB_NHD27OLED_BW u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_BW u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_BW u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_BW u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGS102 u8g(13, 11, 10, 9, 8);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM132 u8g(13, 11, 10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128 u8g(13, 11, 10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128_2X u8g(13, 11, 10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_ST7920_128X64_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_1X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_128X64_4X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_1X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_4X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(13, 11, 10); // SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10
//U8GLIB_ST7920_192X32_4X u8g(10);  // SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10, HW SPI
//U8GLIB_ST7920_202X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_1X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_202X32_4X u8g(18, 16, 17); // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_LM6059 u8g(13, 11, 10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_LM6063 u8g(13, 11, 10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_BW u8g(10, 9);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_BW u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_GR u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_PCF8812 u8g(13, 11, 10, 9, 8);  // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 14, 15, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
//U8GLIB_LC7981_160X80 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16);  // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16);  // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16);  // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_ILI9325D_320x240 u8g(18,17,19,U8G_PIN_NONE,16 );     // 8Bit Com: D0..D7: 0,1,2,3,4,5,6,7 en=wr=18, cs=17, rs=19, rd=U8G_PIN_NONE, reset = 16
//U8GLIB_SBN1661_122X32 u8g(8,9,10,11,4,5,6,7,14,15, 17, U8G_PIN_NONE, 16);  // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 cs1=14, cs2=15,di=17,rw=16,reset = 16
//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X64 u8g(4, 5, 6, 7); // SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new white HalTec OLED)
//U8GLIB_SSD1306_128X64 u8g(10, 9);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); // I2C / TWI 
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST); // Fast I2C / TWI 
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK); // Display which does not send AC
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(10, 9);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X32 u8g(10, 9);             // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SH1106_128X64 u8g(4, 5, 6, 7); // SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new blue HalTec OLED)
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK); // Display which does not send ACK
//U8GLIB_SSD1309_128X64 u8g(13, 11, 10, 9); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1327_96X96_GR u8g(U8G_I2C_OPT_NONE); // I2C
//U8GLIB_SSD1327_96X96_2X_GR u8g(U8G_I2C_OPT_NONE); // I2C
//U8GLIB_UC1611_DOGM240 u8g(U8G_I2C_OPT_NONE); // I2C
//U8GLIB_UC1611_DOGM240 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGM240 u8g(10, 9);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGXL240 u8g(U8G_I2C_OPT_NONE); // I2C
//U8GLIB_UC1611_DOGXL240 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGXL240 u8g(10, 9);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_NHD_C12864 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_NHD_C12832 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(11, 12, 9, 10, 8); // SPI Com: SCK = 11, MOSI = 12, CS = 9, A0 = 10, RST = 8  (SW SPI Nano Board)
//U8GLIB_UC1608_240X64 u8g(13, 11, 10, 9, 8); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8); // HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8); // HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X u8g(13, 11, 10, 9, 8); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8); // HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8); // HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_T6963_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_HT1632_24X16 u8g(3, 2, 4);  // WR = 3, DATA = 2, CS = 4
//U8GLIB_SSD1351_128X128_332 u8g(13, 11, 8, 9, 7); // Arduino UNO: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(76, 75, 8, 9, 7); // Arduino DUE: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(8, 9, 7); // Arduino: HW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(76, 75, 8, 9, 7); // Arduino DUE, SW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128GH_332 u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)
//U8GLIB_SSD1351_128X128GH_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)

U8GLIB_SH1106_128X64 u8g(10, 9, 12, 11, 13);

int cnt;

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( 0, 22, "Hello World!");
}

void setup(void) {
  // flip screen, if required
  // u8g.setRot180();
  
  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }

  cnt = 3;
}

void loop(void) {
  // picture loop
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(1000);
  
  switch(--cnt){
    case 2:
      u8g.setRot90();
      break;
    case 1:
      u8g.setRot180();
      break;
    case 0:
      u8g.setRot270();
      break;
    default:
      u8g.undoRotation();
      cnt = 3;
  }

}




Related:
NodeMCU/ESP8266 + OLED 1.3" 128x64 SPI SH1106, using esp8266-oled-sh1106 library

Saturday, April 18, 2015

Hello World 0.96 inch 128X64 I2C OLED, on Arduino Uno, using u8glib library

It's a 0.96" 128X64 OLED, I2C (or IIC) interface, with SSD1306 driver, 3.3/5V compatible.


There are 4 pin on the OLED module, GND, VCC, SCL and SDA. Connect to Arduino as:
GND - GND on Arduino Uno
VCC - 5V on Arduino Uno
SCL - A5 on Arduino Uno
SDA - A4 on Arduino Uno


u8glib (Universal Graphics Library for 8 Bit Embedded Systems) is a  graphics library with support for many different displays.

This video show how to download u8glib, import the library from the "Add Library" Menu in Arduino IDE, and run the HelloWorld example in the library.

In the HelloWorld, only un-comment the following constructor to make it work:
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);


More examples using 0.96 inch 128X64 I2C OLED:
Walking bitmap on 0.96 inch 128X64 I2C OLED x Arduino Nano
Display waveform on mini OLED with Arduino Nano
Arduino Nano: Capture analog input in Timer Interrupt
Arduino Nano + GY-271 (Digital Compass module) + OLED
Simple Compass - Arduino Nano + GY-271(HMC5883L) + mini-OLED
- NodeMCU (ESP8266) to display on 128x64 I2C OLED

Related:
Hello World 1.3 inch IIC/SPI 128x64 OLED x Arduino, using u8glib library



Monday, April 13, 2015

Arduino Due muilt serial and serialEvent

Arduino Due have 4 hardware serial ports. This example show how to use two serial port together, Serial and Serial3. Serial connect to PC via USB, once data received from Serial, it will be transmitted out to Serial3. Once data received from Serial3, it will be transmitted to Serial.

int LED = 13;
boolean LEDst = false;

void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LEDst);
}

void loop() {
  while (Serial.available() > 0) {
    char a = Serial.read();
    Serial3.write(a);
  }
  
  while (Serial3.available() > 0) {
    char a = Serial3.read();
    Serial.write(a);
    ToggleLED();
  }
}

void ToggleLED(){
  digitalWrite(LED, LEDst = !LEDst);
}

Connect a wire between TX3 and RX3 on Arduino Due board, such that anything type in Arduino IDE Serial Monitor will be sent to Serial, then to Serial3, and loop back to Serial3, and sent back to Serial, to Serial Monitor.
It's another version do the same thing, with serialEvent3() for Serial3.

SerialEvent occurs whenever a new data comes in the hardware serial RX.  This routine is run between each time loop() runs, so using delay inside loop can delay response.  Multiple bytes of data may be available. ~ reference: http://arduino.cc/en/Tutorial/SerialEvent

int LED = 13;
boolean LEDst = false;

void setup() {
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LEDst);
}

void loop() {
  while (Serial.available() > 0) {
    char a = Serial.read();
    Serial3.write(a);
  }
  
}

void serialEvent3() {
  while (Serial3.available() > 0) {
    char a = Serial3.read();
    Serial.write(a);
    ToggleLED();
  }
}

void ToggleLED(){
  digitalWrite(LED, LEDst = !LEDst);
}

Thursday, April 9, 2015

ESP8266-01 open box, power-up test, with minimum config

Just bought a low-cost WiFi module, ESP8266-01. According to the seller, a brand new ESP8266 default run in CWMODE2, AP mode. (Actually, I can't find any official document mention the default mode)

To test if it is operate properly, simple apply 3.3v to VCC and GND, and connect CH_PD to VCC.



The module will run and setup a WiFi AP, named ESP_XXXXXX. You can use a mobile phone to scan the AP, and connect. That means your ESP8266 module is up and run properly.



Then connect it to PC with FTDI (USB-Serial interface). Make sure it's work on 3.3V, or a voltage level converter is need.

Connect as:
To communication with USB serial device, I use Arduino IDE, select port and run Serial Monitor. To connect with ESP8266 with current firmware, select 9600 baud and line end with Both NL & CR. Then can try enter AT command.


I have two devices wifi connected to the AP of ESP8266 in CWMODE 2; a mobile phone (IP: 192.168.4.100) and the PC (IP: 192.168.4.101) runnig the test. I tried to ping other devices from the PC, only the AP of ESP8266 (IP: 192.168.4.1) can be ping, the another connected mobile phone (IP: 192.168.4.100) cannot be reached!


That's my very first test on a brand new ESP8266-01 WiFi module, with everything factory default setting.


Monday, April 6, 2015

Python auto detect Arduino connected serial port

This example TRY to detect Arduino Uno connected serial port automatically, such that no need to hard code "'ttyACM0", "'ttyACM1"... It run on both Python 2 and 3. I test it on Ubuntu Linux only. It's a trial experience only, not a complete solution.



PySerial (ref: http://pyserial.sourceforge.net/pyserial_api.html) provide a function serial.tools.list_ports.comports(), it return an iterable that yields tuples of three strings:
- port name as it can be passed to serial.Serial or serial.serial_for_url()
- description in human readable form
- sort of hardware ID. E.g. may contain VID:PID of USB-serial adapters.

Items are returned in no particular order. It may make sense to sort the items. Also note that the reported strings are different across platforms and operating systems, even for the same device.

To simplify, I assume the port name (eg. /dev/ttyACM0) is in the 1st item returned, and have not handle any other case.

As shown in the post "Get idVendor and idProduct of your Arduino/USB devices", we know VID:PID of Arduino Uno is 2341:0043. So we can compare it with what returned from serial.tools.list_ports.comports() to determine is it Arduino Uno. And for simplify also, I assume it's in VID:PID=2341:0043 format.

findUno.py
import serial.tools.list_ports
import sys
import atexit
import platform

print("=== Auto scan for Arduino Uno connected port===")
print("")
print(platform.system(), platform.release())
print(platform.dist())
print("Python version " + platform.python_version())
print("")

def findArduinoUnoPort():
    portList = list(serial.tools.list_ports.comports())
    for port in portList:
        if "VID:PID=2341:0043" in port[0]\
            or "VID:PID=2341:0043" in port[1]\
            or "VID:PID=2341:0043" in port[2]:
            print(port)
            print(port[0])
            print(port[1])
            print(port[2])

            #please note: it is not sure [0]
            #returned port[] is no particular order
            #so, may be [1], [2]
            return port[0]

def doAtExit():
    if serialUno.isOpen():
        serialUno.close()
        print("Close serial")
        print("serialUno.isOpen() = " + str(serialUno.isOpen()))

atexit.register(doAtExit)

unoPort = findArduinoUnoPort()
if not unoPort:
    print("No Arduino Uno found")
    sys.exit("No Arduino Uno found - Exit")

print("Arduino Uno found: " + unoPort)
print()

serialUno = serial.Serial(unoPort, 9600)
print("serialUno.isOpen() = " + str(serialUno.isOpen()))

while True:
    while (serialUno.inWaiting()==0):
        pass
    valueRead = serialUno.readline(500)
    print(valueRead)



In Arduino Uno side, just a simple program to repeatly call Serial.println() for testing.
AnalogInSerialOut.ino
const int analogIn = A0;
int analogVal = 0;

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

void loop() {

  analogVal = analogRead(analogIn);
  Serial.println(analogVal);
  delay(1000);
}

IoT experience: Arduino Uno + Ethernet Shield send data to dweet.io and freeboard.io

It's a IoT experience, run on Arduino Uno + Ethernet Shield, read analog input from A0, send to dweet.io and freeboard.io.

VIew on dweet.io
freeboard.io


dweet.io is simple publishing and subscribing for machines, sensors, devices, robots, and gadgets (we just call them things). We call published messages ‘dweets’. It’s helpful to think of dweet.io as a Twitter for things, in fact.

With freeboard.io, we can create simple dashboards for devices, include dweet.io things.



The code on Arduino Uno, AnalogInDweetIoRepeat.ino. Modified from Web Client Repeating example (http://arduino.cc/en/Tutorial/WebClientRepeating).

/*
Reference:
 http://arduino.cc/en/Tutorial/WebClientRepeating
 */

#include <SPI.h>
#include <Ethernet.h>

const int analogIn = A0;
int analogVal = 0;

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);

// initialize the library instance:
EthernetClient client;

char server[] = "www.dweet.io";

unsigned long lastConnectionTime = 0;             // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds
// the "L" is needed to use long type numbers

void setup() {
  // start serial port:
  Serial.begin(9600);
  Serial.println("--- Start ---");
  
  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac, ip); 
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if ten seconds have passed since your last connection,
  // then connect again and send data:
  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();
  }

}

// this method makes a HTTP connection to the server:
void httpRequest() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    analogVal = analogRead(analogIn);
    
    // Make a HTTP request:
    String s = "POST /dweet/for/arduinotest?A0=";
    s.concat(analogVal);
    Serial.println(s);
    client.println(s);
    
    client.println("Host: www.dweet.io");
    client.println("Connection: close");
    client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  }
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
  }
}


This video show how it run and view on dweet.io and freeboard.io. Pin A0 is open(float) here, so the value is random.


Related example on my another blog about Raspberry Pi:
IoT at dweet.io, Python on RPi 2 to send data to Cloud
- Create dashboards for dweet.io things with freeboard.io

Related:
- Arduino Due + ESP8266 + DHT11, to update dweet.io

NodeMCU version:
NodeMCU act as WiFi client to update dweet.io


Updated@2017-06-15:
Somebody complain the example not work, I tried agin, Arduino Uno + Ethernet Shield, without change. And found it still work as expected.


Once you make it run, you can check the thing at http://dweet.io/follow/arduinotest


Friday, April 3, 2015

Find usb device of specified idVendor and idProduct in Python with PyUSB.

This simple example show how to find the USB device with specified idVendor and idProduct in Python with PyUSB, and print it's details.


- To install PyUSB, refer to the post "Download and Install PyUSB for Python 2 and 3".

- To know the Vendor ID and Product ID of your device, refer the post "Get idVendor and idProduct of your Arduino/USB devices".

- Enter the code, replace with your idVendor and idProduct. It run on both Python 2 and 3.

import usb.core
import usb.util

# find Arduino Uno
dev = usb.core.find(idVendor=0x2341, idProduct=0x0043)

# was it found?
if dev is None:
    raise ValueError('Device not found')

print(repr(dev))
print('VendorID  = 0x%04x'%dev.idVendor)
print('ProductID = 0x%04x'%dev.idProduct)
print
print(dev)


Example output of Arduino Uno rev 3, with idVendor=2341, idProduct=0043
<DEVICE ID 2341:0043 on Bus 002 Address 010>
VendorID  = 0x2341
ProductID = 0x0043
DEVICE ID 2341:0043 on Bus 002 Address 010 =================
 bLength                :   0x12 (18 bytes)
 bDescriptorType        :    0x1 Device
 bcdUSB                 :  0x110 USB 1.1
 bDeviceClass           :    0x2 Communications Device
 bDeviceSubClass        :    0x0
 bDeviceProtocol        :    0x0
 bMaxPacketSize0        :    0x8 (8 bytes)
 idVendor               : 0x2341
 idProduct              : 0x0043
 bcdDevice              :    0x1 Device 0.01
 iManufacturer          :    0x1 Error Accessing String
 iProduct               :    0x2 Error Accessing String
 iSerialNumber          :   0xdc Error Accessing String
 bNumConfigurations     :    0x1
  CONFIGURATION 1: 100 mA ==================================
   bLength              :    0x9 (9 bytes)
   bDescriptorType      :    0x2 Configuration
   wTotalLength         :   0x3e (62 bytes)
   bNumInterfaces       :    0x2
   bConfigurationValue  :    0x1
   iConfiguration       :    0x0 
   bmAttributes         :   0xc0 Self Powered
   bMaxPower            :   0x32 (100 mA)
    INTERFACE 0: CDC Communication =========================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x0
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x1
     bInterfaceClass    :    0x2 CDC Communication
     bInterfaceSubClass :    0x2
     bInterfaceProtocol :    0x1
     iInterface         :    0x0 
      ENDPOINT 0x82: Interrupt IN ==========================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x82 IN
       bmAttributes     :    0x3 Interrupt
       wMaxPacketSize   :    0x8 (8 bytes)
       bInterval        :   0xff
    INTERFACE 1: CDC Data ==================================
     bLength            :    0x9 (9 bytes)
     bDescriptorType    :    0x4 Interface
     bInterfaceNumber   :    0x1
     bAlternateSetting  :    0x0
     bNumEndpoints      :    0x2
     bInterfaceClass    :    0xa CDC Data
     bInterfaceSubClass :    0x0
     bInterfaceProtocol :    0x0
     iInterface         :    0x0 
      ENDPOINT 0x4: Bulk OUT ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :    0x4 OUT
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x1
      ENDPOINT 0x83: Bulk IN ===============================
       bLength          :    0x7 (7 bytes)
       bDescriptorType  :    0x5 Endpoint
       bEndpointAddress :   0x83 IN
       bmAttributes     :    0x2 Bulk
       wMaxPacketSize   :   0x40 (64 bytes)
       bInterval        :    0x1

Get idVendor and idProduct of your Arduino/USB devices

To know the idVendor and idProduct of your Arduino/USB devices, in Linux system, we can use the dmesg command, to read messages from kernel ring buffer.


- with your Arduino/USB devices NOT connected, run the command to clear the buffer.
$ sudo dmesg -c

- Connect Arduino/USB devices, enter the command:
$ dmesg

- The latest connect device will be shown, include its idVendor and idProduct:

Download and Install PyUSB for Python 2 and 3

PyUSB is a Python module for easy accessing USB devices.



To install PyUSB on Linux, browse SourceForge page, download the latest version. Unpack the downloaded file. Then switch to the unpacked directory, run the command:

For Python 2:
$ sudo python setup.py install

For Python 3:
$ sudo python3 setup.py install




Example of finding usb of Arduino Uno board using Python with PyUSB.

Thursday, April 2, 2015

Python to plot graph of serial data from Arduino Uno analog input

It's a simple example to read analog input from Arduino Uno, send to PC via USB serial. In the PC side, running Python on Linux, plot the received serial graphically using matplotlib and drawnow library.




Arduino side:


AnalogInSerialOut.ino
const int analogIn = A0;
int analogVal = 0;

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

void loop() {

  analogVal = analogRead(analogIn);
  Serial.println(analogVal);
  delay(1000);
}

PC side running Python 2.7.6, plotArduino.py. It's the example code run in the demo video.
import serial
import matplotlib.pyplot as plt
from drawnow import *

values = []

plt.ion()
cnt=0

serialArduino = serial.Serial('/dev/ttyACM0', 19200)

def plotValues():
    plt.title('Serial value from Arduino')
    plt.grid(True)
    plt.ylabel('Values')
    plt.plot(values, 'rx-', label='values')
    plt.legend(loc='upper right')

#pre-load dummy data
for i in range(0,26):
    values.append(0)
    
while True:
    while (serialArduino.inWaiting()==0):
        pass
    valueRead = serialArduino.readline()

    #check if valid value can be casted
    try:
        valueInInt = int(valueRead)
        print(valueInInt)
        if valueInInt <= 1024:
            if valueInInt >= 0:
                values.append(valueInInt)
                values.pop(0)
                drawnow(plotValues)
            else:
                print "Invalid! negative number"
        else:
            print "Invalid! too large"
    except ValueError:
        print "Invalid! cannot cast"
    



Modified version of plotArduino.py:
- It seem that 19200 baud is not stable in my unit, so change to 9600. (Have to modify Arduino side also)
- Add some line to indicate status.
- Add atexit handling.
- Make it work on both Python 2 and 3.

import serial
import matplotlib.pyplot as plt
from drawnow import *
import atexit

values = []

plt.ion()
cnt=0

serialArduino = serial.Serial('/dev/ttyACM0', 9600)

def plotValues():
    plt.title('Serial value from Arduino')
    plt.grid(True)
    plt.ylabel('Values')
    plt.plot(values, 'rx-', label='values')
    plt.legend(loc='upper right')

def doAtExit():
    serialArduino.close()
    print("Close serial")
    print("serialArduino.isOpen() = " + str(serialArduino.isOpen()))

atexit.register(doAtExit)

print("serialArduino.isOpen() = " + str(serialArduino.isOpen()))

#pre-load dummy data
for i in range(0,26):
    values.append(0)
    
while True:
    while (serialArduino.inWaiting()==0):
        pass
    print("readline()")
    valueRead = serialArduino.readline(500)

    #check if valid value can be casted
    try:
        valueInInt = int(valueRead)
        print(valueInInt)
        if valueInInt <= 1024:
            if valueInInt >= 0:
                values.append(valueInInt)
                values.pop(0)
                drawnow(plotValues)
            else:
                print("Invalid! negative number")
        else:
            print("Invalid! too large")
    except ValueError:
        print("Invalid! cannot cast")




To install matplotlib, drawnow and pyserial:

for Python 2
$ sudo apt-get install python-matplotlib
$ sudo apt-get install python-pip
$ sudo pip install drawnow
$ sudo pip install pyserial

for Python 3
$ sudo apt-get install python3-matplotlib
$ sudo apt-get install python3-pip
$ sudo pip3 install drawnow
$ sudo pip3 install pyserial


Updated@2017-06-17:
It's a similarity example without using drawnow, tested on Raspberry Pi and PC/Ubuntu 17.04/Python 3.6 ~ Python run on Raspberry Pi (and PC running Ubuntu) to plot serial data from ESP8266/NodeMCU


My Arduino 1.6.3 cannot detect port

Just tried the new released Arduino IDE 1.6.3 on Ubuntu Linux 14.04, the first time run is ok.

But after a moment, it cannot detect connected usb port, with error following error. Even after reboot.
~/arduino-1.6.3$ ./arduino
Exception in thread "cc.arduino.packages.discoverers.serial.SerialBoardsLister" java.lang.NullPointerException
 at processing.app.Platform.resolveDeviceByVendorIdProductId(Platform.java:143)
 at processing.app.linux.Platform.resolveDeviceAttachedTo(Platform.java:141)
 at cc.arduino.packages.discoverers.serial.SerialBoardsLister.run(SerialBoardsLister.java:73)
 at java.util.TimerThread.mainLoop(Timer.java:555)
 at java.util.TimerThread.run(Timer.java:505)

Tried to switch back to Arduino 1.6.0, it can detect usb as normal.


This video show how:

ARDUINO 1.6.3 just released

ARDUINO 1.6.3 just released.

BUT, I tried it with problem!
Please read "My Arduino 1.6.3 cannot detect port".