Arduino & Python Communications
Lab 1
Lab 1
The main objective of this lab is to get familiar with Arduino prototyping. This will be achieved by establishing a link between the main computer, the Arduino UNO, and the display peripheral in order to learn about communication protocols (I2C, Serial, etc.) as well as programming basics in the Arduino language and Python.
Furthermore, we will implement a variety of peripherals to communicate with the Arduino board and a Python script. The peripherals include Bluetooth modules, physical buttons, and even an OLED display! Once we setup the peripherals to the Arduino, the options of functionality we can implement are practically limitless. Useful and fun functions, such as an actual weather forecasting API, will be added to the circuit in a series of objectives (1 to 4), that will challenge you to think creatively in the process.
By the end of this lab, you will feel comfortable using the Arduino board and language, as well as Python, to create various devices of your own. The world of wireless and wired connectivity through Serial connection and Bluetooth will be opened to you, and you will even have a finished, tangible product that displays weather at the very end of this lab.
There will be FOUR main objectives achieved in the completion of this lab:
1.) We begin by first opening up the Arduino IDE and opening an example sketch. This can be done by navigating to File >> Examples >> Basics >> Blink.
2.) Upload the code onto your Arduino and run it. Make sure to connect your Arduino via USB to your computer prior to uploading the code. It should look similar to this:
Notice the yellow LED flashing on the Arduino board!
3.) Next, let's modify the code so that the LED stays on for 2 seconds, then off for 0.5 seconds. This can be easily done with the following code:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(500); // wait for a second
}
The delay() command is measured in milliseconds! Run your code by uploading it onto the Arduino and verify that it works as intended.
4.) Now let's implement a counter into the code so that it increments and prints every time the LED blinks. The following code will accomplish this:
int Counter;
String input_cmd;
int Status;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Counter = 0;
Serial.begin(9600);
While (!Serial)
{
;
}
digitalWrite(LED_BUILTIN, LOW);
}
// the loop function runs over and over again forever
void loop() {
Serial.println(Counter); //prints the counter value
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(500); // wait for a second
Counter++; //counter incremented by 1
}
By introducing a new integer type variable called Counter, we can keep track of how many times the LED blinks, and print it out to the Serial Monitor!
5.) Finally, we want to be able to send commands to the Arduino via Serial communication to START or STOP the blinking process. We can implement this function with the following code:
int Counter;
String input_cmd;
int Status;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial)
{
;
}
Counter = 0;
Status = false;
digitalWrite(LED_BUILTIN, LOW);
Serial.println("Enter 'START' to begin or 'STOP' to terminate LED blinking");
}
// the loop function runs over and over again forever
void loop() {
if (Serial.available() > 0) { //checks Serial buffer for data
input_cmd = Serial.readString(); //stores input string from serial into input_cmd
Serial.println(input_cmd);
if (input_cmd == "START\n") { //if the input is the string "START", it will begin the LED sequence
Serial.println("Starting LED Blink Sequence...");
Status = true;
} else if (input_cmd == "STOP\n") { //if the input string is "STOP", it will stop the LED sequence
Serial.println("Stopping LED Blink Sequence...");
Status = false;
}
}
if (Status) {
Serial.println(Counter); //prints the counter value
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(500); // wait for a second
Counter++; //counter incremented by 1
}
}
The code will continually check for Serial input with an if-statement and when it detects the words START or STOP, it will correspondingly pause or begin the blinking process again! Upload the code to your Arduino and test it to make sure it works properly.
1.) First we will set up the circuit according to the following diagram:
2.) Next, we require a few libraries to write the source code. Download the following libraries:
Libraries can be downloaded by navigating through the taskbar:
Arduino >> Sketch >> Include Library >> Manage Libraries...
The following window should pop up:
Simply type the name of the library you wish to install in the search bar and click install.
You should see now see the libraries in your list of libraries:
3.) Now that all the necessary libraries are installed, copy and paste the following code to a new Arduino Sketch file:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
/*
* The following is a list of global variables declared and used throughout the code
*/
String input_cmd; //Input string from Serial
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// init done
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.clearDisplay();
display.display();
//Setting Text Display settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
}
void loop() {
display.clearDisplay();
display.setCursor(0,0);
display.println(input_cmd);
display.display();
if ((Serial.available() > 0)) {
input_cmd = Serial.readString();
}
}
4.) Save and compile the code, then upload it to your Arduino. You can now print through the Serial monitor any text that you want to display on the OLED!
For my example, once the code is uploaded to the Arduino, you can open up the Serial Monitor by navigating to:
Arduino >> Tools >> Serial Monitor
Then, type whatever phrase you would like to print (I want to print my initials and "Hello, World!"), and hit the "Send" button.
Congratulations! You have successfully printed to the OLED. Your final results should resemble something like this:
1.) First, we build the pull-up resistor circuit according to the figure below:
The input pin will be connected to the Arduino's digital pin 4. Below is the circuit with the button wired correctly:
2.) Next, we add a function to our sketch that will display and increment a counter once every second. When the button is pressed, the counter should toggle stop/resume. To do this, we use the following code:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
/*
* The following is a list of global variables declared and used throughout the code
*/
String input_cmd; //Input string from Serial
int counter; //counter variable
unsigned long last_time;
unsigned long current_time;
int last_state;
int current_state;
boolean pause;
void setup() {
// put your setup code here, to run once:
pinMode(4, INPUT);
Serial.begin(9600);
while (!Serial) {
;
}
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// init done
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.clearDisplay();
//clearing the display from adafruit logo
display.display();
//initializing the text settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
counter = 0;
current_time = millis();
current_state = digitalRead(4);
pause = false;
input_cmd = "";
}
void loop() {
// This will continually display the input_cmd string and the count
display.clearDisplay();
display.setCursor(0,0);
display.println(input_cmd);
display.setCursor(0,24);
display.println(counter);
display.display();
if ((Serial.available() > 0)) {
input_cmd = Serial.readString();
}
stopwatch(&last_time, ¤t_time, &last_state, ¤t_state, &counter, &pause);
}
void stopwatch( unsigned long *last_time, unsigned long *current_time,
int *last_state, int *current_state, int *counter, boolean *pause) {
*last_state = *current_state;
*current_time = millis();
*current_state = digitalRead(4);
if ((*current_state == 0) && (*last_state == 1)) {
*pause = !*pause;
}
if ((*current_time - *last_time >= 1000) && (!*pause)) {
*last_time = *current_time;
*counter = *counter + 1;
}
}
3.) Compile, upload, and run the code. The results should be a functional stopwatch counter.
4.) The final step involves replacing the physical pull-up resistor circuit with Arduino's built-in pull-up/pull-down resistor. This is done by replacing the "pinMode(4, INPUT);" line to "pinMode(4, INPUT_PULLUP);" in void setup(). The section of the code is below:
void setup() {
// put your setup code here, to run once:
pinMode(4, INPUT_PULLUP);
Serial.begin(9600);
while (!Serial) {
;
}
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// init done
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.clearDisplay();
//clearing the display from adafruit logo
display.display();
//initializing the text settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
counter = 0;
current_time = millis();
current_state = digitalRead(4);
pause = false;
input_cmd = "";
}
5.) Congratulations! The objective is successful achieved, and the final product should work flawlessly.
1.) This portion of the lab assumes Python3 is already installed and functional on the computer, and that the computer is a MacBook of some sort (sorry, no Windows!).
2.) Install the PySerial library using the command:
$ pip3 install pyserial
3.) Once successfully installed, we need to write a Python module that creates a random number, then sends that number over to the Arduino via Serial connection. The following is the source code for the Python module:
import serial
import random
from time import sleep
with serial.Serial('/dev/cu.usbmodem1411', 9600, timeout = 1) as ser:
key = input("Press enter to start")
# sleep(2)
print(ser.name)
random_int = random.randint(0,10)
print(random_int)
s = str(random_int).encode()
ser.write(s)
Remember to replace the '/dev/cu.usbmodem1411' portion of the code with the appropriate port that the Arduino is connected to on your computer! Otherwise, this will not establish a proper connection.
Note that the random_int variable is encoded prior to sending it to the Arduino. This is because the Arduino reads from Serial in bytes! If we do not encode the variable prior to sending it, the Arduino will not read the proper integer value.
4.) Next, we need to create an Arduino sketch that captures the information sent via Serial and use it to control the LED. The following is the source code for the Arduino:
int timer;
void setup() {
Serial.begin(9600);
while (!Serial){};
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
if (Serial.available() > 0) {
timer = Serial.parseInt();
Serial.println(timer);
Serial.println(timer*1000);
timer = timer*1000;
digitalWrite(LED_BUILTIN, HIGH);
delay(timer);
digitalWrite(LED_BUILTIN, LOW);
}
}
Notice the Serial.parseInt() function is called to properly parse, or analyze, the information we receive from Serial.
5.) Great! You should now have a functional system that creates a random integer in Python, sends the integer over to the Arduino via Serial, and correspondingly turns the LED light on for the number of seconds based on the random number. To test the program, connect all peripherals, upload the Arduino code, then run the python code through your IDE of choice. For command line execution, you can use:
$ python [your_saved_file].py
Remember not to have your Arduino Serial Monitor open as it will not allow Python to connect to the Serial port! Your Arduino's built-in LED should stay on for the random number of seconds as expected.
1. The first thing we must do is install the "requests" library for Python. This can be done through the command line:
$ git clone git://github.com/requests/requests.git
$ cd requests
$ pip install .
Note that you must have git installed in order to use the "git" command: (http://burnedpixel.com/blog/setting-up-git-and-github-on-your-mac/)
2.) Once we have the library, we must create a python script to utilize the metaweather API, but first, look up your city's id using the following template:
www.metaweather.com/api/location/search/query?=(your_city)
I live in San Diego, CA, so I would simply enter the following URL to to my browser:
www.metaweather.com/api/location/search/query?=san
From here, note the "woeid" (Where On Earth ID) that corresponds to your city of residence. For my example, San Diego's ID is 2487889.
3.) Now we are ready to use the Python code for the weather API:
import requests
import serial
from time import sleep
r = requests.get('http://www.metaweather.com/api/location/2487889', )
response = r.json()
ard_out = 'The weather in San Diego is ' + response['consolidated_weather'][0]['weather_state_name']
with serial.Serial('/dev/cu.usbmodem1411', 9600) as ser:
sleep(2)
ser.write(ard_out.encode())
Notice that the JSON file is stored in a object called response, and that we can obtain the weather for the current day by indexing and searching for certain key values within the JSON file. Also, be sure to edit the ard_out string to say your city, and not "San Diego" (unless you live here too!).
4.) Let us set up the circuit on the breadboard for the OLED to display the weather information from the Python script. This procedure was explained earlier in Objective 2, so feel free to reference it.
5.) Once the circuit is ready, upload the Arduino code to the board so that we can properly display the weather information:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
/*
* The following is a list of global variables declared and used throughout the code
*/
String input_cmd; //Input string from Serial
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial) {};
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// init done
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.clearDisplay();
//clearing the display from adafruit logo
display.display();
//initializing the text settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
}
void loop() {
// This will continually display the input_cmd string and the count
// display.clearDisplay();
// display.println(input_cmd);
// display.display();
if ((Serial.available() > 0)) {
input_cmd = Serial.readString();
display.clearDisplay();
display.println(input_cmd);
display.display();
}
}
Make sure to upload your code to the Arduino board after you finish compiling.
6.) Finally, we can test everything to ensure that the weather is properly displayed on the OLED. Once the Arduino code is uploaded, run the Python script through either the command line of your IDE. You should see the current weather of your city displayed on the OLED. The final result should look similar to this:
Congratulations! You have officially completed Objective 3B. You should now have a basic understanding of how to implement APIs using the Python "requests" library and displaying the information on an OLED through an Arduino.
1.) Before we dive into this objective, there are some prerequisites that must be met. First, set up the hardware circuit so that both the button and the OLED from Objective 2 function properly. Then we must download the drivers to use with our BLE module (https://learn.adafruit.com/adafruits-raspberry-pi-lesson-5-using-a-console-cable?view=all#software-installation-mac).
Next, connect the BLE module to your computer as depicted below:
The BLE module must also be wired to the Arduino board. Refer to the diagram below for wiring specifications:
2.) Now we can use a sample code to get our BLE modules connected to one another:
#include <AltSoftSerial.h>
AltSoftSerial BTserial;
char c=' ';
boolean NL = true;
void setup()
{
Serial.begin(9600);
while(!Serial){};
BTserial.begin(9600);
Serial.println("BTserial started");
}
void loop()
{
// Read from the Bluetooth module and send to the Arduino Serial Monitor
if (BTserial.available())
{
c = BTserial.read();
Serial.write(c);
}
// Read from the Serial Monitor and send to the Bluetooth module
if (Serial.available())
{
c = Serial.read();
// do not send line end characters to the HM-10
if (c!=10 & c!=13 )
{
BTserial.write(c);
}
// Copy the user input to the main window, as well as the Bluetooth module
// If there is a new line print the ">" character.
if (NL) {
Serial.print("\r\n>");
NL = false;
}
Serial.write(c);
if (c==10) {
NL = true;
}
}
}
Upload the above code into your Arduino, and type the "AT" status command from the Serial Monitor. The response you see should be "OK". Next, we perform the same step, but for our Python code:
import serial, sys
from time import sleep
def read_BLE( ser ):
msg = ""
if( ser.in_waiting > 0 ):
msg = ser.readline( ser.in_waiting ).decode('utf-8')
return msg
with serial.Serial(port='/dev/cu.usbserial', baudrate=9600, timeout=1) as ser:
while(True) :
command = input("Either (1) hit ENTER to read BLE, (2) send an AT command, or (3) press q to exit: ")
if( command == "") :
print( "> " + read_BLE(ser) )
elif (command == 'q' or command == 'Q'):
print("Goodbye")
sys.exit(0)
else:
ser.write( command.encode('utf-8') )
sleep(0.5) # wait for a response
print( "> " + read_BLE(ser) )
From the Python window, set the role of the Laptop HM-10 module to central and disable auto-connect. This is done through the commands:
We also need to set the role of the Arduino HM-10 to peripheral, so use the following command through the Arduino Serial Monitor:
3.) Find the address of each HM-10 module by using the command:
Keep note of the two addresses as we will need it to connect to one another.
4.) From the Python window, connect the laptop's HM-10 module to the Arduino's HM-10 module using the MAC address found in step 3:
5.) One the BLE modules are connected, you should be able to see input from the Python window in the Arduino Serial Monitor, and vice versa!
6.) Let us implement the button (connected to input pin 4) so that we can toggle between sleep/awake for the HM-10 on the Arduino. The following code will implement this function:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
#include <AltSoftSerial.h>
AltSoftSerial BTserial;
char c =' ';
boolean NL = true;
int last_state;
int current_state;
boolean sleep = 0;
int readytowake = 0;
void setup()
{
pinMode (4, INPUT_PULLUP);
Serial.begin(9600);
while(!Serial){};
BTserial.begin(9600);
Serial.println("BTserial started");
current_state = digitalRead(4);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
//initializing the text settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
}
void loop()
{
//Constantly checks for the when the button is pressed
button(&last_state, ¤t_state, &sleep);
// Check the sleep variable to either wake up/sleep the Bluetooth modulw
if (sleep && !readytowake)
{
BTserial.write("AT");
delay(500);
BTserial.write("AT+SLEEP");
delay(100);
readytowake = 1;
}
if (!sleep && readytowake)
{
for (int i = 0; i < 80; i++)
{
BTserial.write('5');
}
readytowake = 0;;
}
// Read from the Bluetooth module and send to the Arduino Serial Monitor
if (BTserial.available())
{
c = BTserial.read();
//The ';' character will clear the display
if (c == ';')
{
display.clearDisplay();
display.setCursor(0,0);
display.display();
}
else
{
Serial.write(c);
display.print(c);
display.display();
}
}
// Read from the Serial Monitor and send to the Bluetooth module
if (Serial.available())
{
c = Serial.read();
// do not send line end characters to the HM-10
if (c!=10 & c!=13 )
{
BTserial.write(c);
}
// Copy the user input to the main window, as well as the Bluetooth module
// If there is a new line print the ">" character.
if (NL)
{
Serial.print("\r\n>");
NL = false;
}
Serial.write(c);
if (c==10)
{
NL = true;
}
}
}
void button( int *last_state, int *current_state, boolean *sleep)
{
// delay(100);
*last_state = *current_state;
*current_state = digitalRead(4);
if ((*current_state == 0) && (*last_state == 1))
{
*sleep = !*sleep;
}
}
Upload the code to your Arduino board, and test it.
When you press the button on the Arduino, you should notice the HM-10 module go to sleep (indicated by the absence of a blinking red LED).
7.) Next, we want to implement the same weather API functionality from Objective 3 into our current setup with the HM-10 modules. This time, instead of the Python script sending data via Serial, we want to send weather information from the API from the Python script to the Arduino and the OLED through Bluetooth communication. The following Python code accomplishes this:
#Import libraries
import serial
import sys
from time import sleep
import requests
def read_BLE (ser):
msg = ""
if (ser.in_waiting > 0):
msg = ser.readline(ser.in_waiting).decode('utf-8')
return msg
with serial.Serial(port='/dev/cu.usbserial', baudrate = 9600, timeout = 1) as ser:
set_role= "AT+ROLE1"
set_imme= "AT+IMME1"
set_noti= "AT+NOTI1"
set_connect = "AT+CON3403DE349771"
ser.write(set_role.encode())
sleep(0.5)
print("> " + read_BLE(ser))
ser.write(set_imme.encode())
sleep(0.5)
print("> " + read_BLE(ser))
ser.write(set_connect.encode())
sleep(0.5)
print("> " + read_BLE(ser))
ser.write(set_noti.encode())
sleep(0.5)
print("> " + read_BLE(ser))
connection_secure = True
while(True):
ble_in = read_BLE(ser)
print("> " + ble_in)
sleep(0.1)
if (ble_in == "OK+LOST"):
print("Connection Lost")
connection_secure = False
command = input("To reconnect: press ENTER")
ser.write(set_connect.encode())
sleep(0.5)
ble_in = read_BLE(ser)
if (ble_in == "OK+CONNAOK+CONN"):
print("> Reconnection successful")
connection_secure = True
else:
print("> Reconnection failed. Returning to Main Menu")
connection_secure = True
if (connection_secure):
command = input("""
(1) hit ENTER to read BLE,
(2) send an AT command or Text to display on OLED,
(3) type "weather" to display weather,
(4) type ";" to clear OLED,
(4) press q to exit: """)
if (command == ""):
continue
elif (command == 'q' or command == 'Q'):
print ("Disconnecting BLE Module...")
command = "AT"
ser.write(command.encode())
print ("Goodbye")
sys.exit(0)
elif (command == 'weather' or command == 'WEATHER'):
print ("Weather is being displayed on OLED")
r = requests.get('http://www.metaweather.com/api/location/2487889', )
response = r.json()
ard_out = 'The weather in San Diego is ' + response['consolidated_weather'][0]['weather_state_name']
ser.write(ard_out.encode())
else:
ser.write (command.encode('utf-8'))
sleep(0.5) #wait for a response
print ("> " + read_BLE(ser))
Remember to change the set_connect variable to be the MAC address of your Arduino's HM-10. The API request should also be changed to incorporate your own city's woeID, not San Diego (unless you also live in San Diego)!
Try to run the code along with the Arduino's code, and test it to ensure it works properly.
For example, when you enter "weather" into the Python window as a command, you should see something like this on your OLED:
8.) Lastly, we want to try to run this entire setup from a 9V battery on the Arduino board. Simply connect a 9V battery to the Arduino's power input, and disconnect the Arduino from your laptop. Here is an example of what you should have:
9.) Congratulations! You have successfully completed the final objective of this lab. You should be able to get weather data for you current city of residence through the Python script, then communicate the data via Bluetooth to the Arduino to display on the OLED.