“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.
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);
}
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:
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;
}
}
}
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".
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);
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
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);
}
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.
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
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.
/*
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.
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.
- 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
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:
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:
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.
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")
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.