Skip to content

Commit 6776e9d

Browse files
authored
Merge pull request #10 from ladyada/master
Many updates, new functions, flow control, simplified examples
2 parents 0ed72ce + 47222c6 commit 6776e9d

7 files changed

+716
-227
lines changed

adafruit_espatcontrol.py

Lines changed: 392 additions & 132 deletions
Large diffs are not rendered by default.

examples/espatcontrol_bitcoinprice.py

Lines changed: 0 additions & 56 deletions
This file was deleted.

examples/espatcontrol_cheerlights.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
This example will query ThingSpeak channel 1417 "CheerLights" and display the
3+
color on a NeoPixel ring or strip
4+
"""
5+
import gc
6+
import time
7+
import board
8+
import busio
9+
from digitalio import DigitalInOut
10+
import adafruit_espatcontrol
11+
import neopixel
12+
import ujson
13+
import adafruit_fancyled.adafruit_fancyled as fancy
14+
15+
16+
17+
# Get wifi details and more from a settings.py file
18+
try:
19+
from settings import settings
20+
except ImportError:
21+
print("WiFi settings are kept in settings.py, please add them there!")
22+
raise
23+
24+
# CONFIGURATION
25+
TIME_BETWEEN_QUERY = 10 # in seconds
26+
27+
# Cheerlights!
28+
DATA_SOURCE = "http://api.thingspeak.com/channels/1417/feeds.json?results=1"
29+
DATA_LOCATION = ["feeds", 0, "field2"]
30+
31+
uart = busio.UART(board.TX, board.RX, timeout=0.1)
32+
resetpin = DigitalInOut(board.D5)
33+
rtspin = DigitalInOut(board.D9)
34+
35+
# Create the connection to the co-processor and reset
36+
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, run_baudrate=460800,
37+
reset_pin=resetpin,
38+
rts_pin=rtspin, debug=True)
39+
esp.hard_reset()
40+
41+
# neopixels
42+
pixels = neopixel.NeoPixel(board.A1, 16, brightness=0.3)
43+
pixels.fill(0)
44+
builtin = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1)
45+
builtin[0] = 0
46+
47+
# we'll save the value in question
48+
last_value = value = None
49+
the_time = None
50+
times = 0
51+
52+
def get_value(response, location):
53+
"""Extract a value from a json object, based on the path in 'location'"""
54+
try:
55+
print("Parsing JSON response...", end='')
56+
json = ujson.loads(response)
57+
print("parsed OK!")
58+
for x in location:
59+
json = json[x]
60+
return json
61+
except ValueError:
62+
print("Failed to parse json, retrying")
63+
return None
64+
65+
while True:
66+
try:
67+
while not esp.is_connected:
68+
builtin[0] = (100, 0, 0)
69+
# settings dictionary must contain 'ssid' and 'password' at a minimum
70+
esp.connect(settings)
71+
builtin[0] = (0, 100, 0)
72+
# great, lets get the data
73+
print("Retrieving data source...", end='')
74+
builtin[0] = (100, 100, 0)
75+
header, body = esp.request_url(DATA_SOURCE)
76+
builtin[0] = (0, 0, 100)
77+
print("Reply is OK!")
78+
except (RuntimeError, adafruit_espatcontrol.OKError) as e:
79+
print("Failed to get data, retrying\n", e)
80+
continue
81+
print('-'*40, "Size: ", len(body))
82+
print(str(body, 'utf-8'))
83+
print('-'*40)
84+
# For mystery reasons, there's two numbers before and after the json data
85+
lines = body.split(b'\r\n') # so split into lines
86+
value = get_value(lines[1], DATA_LOCATION) # an get the middle chunk
87+
builtin[0] = (100, 100, 100)
88+
if not value:
89+
continue
90+
print(times, the_time, "value:", value)
91+
92+
if last_value != value:
93+
color = int(value[1:],16)
94+
red = color >> 16 & 0xFF
95+
green = color >> 8 & 0xFF
96+
blue = color& 0xFF
97+
gamma_corrected = fancy.gamma_adjust(fancy.CRGB(red, green, blue)).pack()
98+
99+
pixels.fill(gamma_corrected)
100+
last_value = value
101+
times += 1
102+
103+
# normally we wouldn't have to do this, but we get bad fragments
104+
header = body = None
105+
gc.collect()
106+
print(gc.mem_free()) # pylint: disable=no-member
107+
time.sleep(TIME_BETWEEN_QUERY)

examples/espatcontrol_countviewer.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
"""
2+
This example will access an API, grab a number like hackaday skulls, github
3+
stars, price of bitcoin, twitter followers... if you can find something that
4+
spits out JSON data, we can display it!
5+
"""
6+
import gc
7+
import time
8+
import board
9+
import busio
10+
from digitalio import DigitalInOut
11+
import adafruit_espatcontrol
12+
from adafruit_ht16k33 import segments
13+
import neopixel
14+
import ujson
15+
16+
# Get wifi details and more from a settings.py file
17+
try:
18+
from settings import settings
19+
except ImportError:
20+
print("WiFi settings are kept in settings.py, please add them there!")
21+
raise
22+
23+
# CONFIGURATION
24+
PLAY_SOUND_ON_CHANGE = False
25+
NEOPIXELS_ON_CHANGE = False
26+
TIME_BETWEEN_QUERY = 60 # in seconds
27+
28+
# Some data sources and JSON locations to try out
29+
30+
# Bitcoin value in USD
31+
DATA_SOURCE = "http://api.coindesk.com/v1/bpi/currentprice.json"
32+
DATA_LOCATION = ["bpi", "USD", "rate_float"]
33+
34+
# Github stars! You can query 1ce a minute without an API key token
35+
#DATA_SOURCE = "https://api.github.com/repos/adafruit/circuitpython"
36+
#if 'github_token' in settings:
37+
# DATA_SOURCE += "?access_token="+settings['github_token']
38+
#DATA_LOCATION = ["stargazers_count"]
39+
40+
# Youtube stats
41+
#CHANNEL_ID = "UCpOlOeQjj7EsVnDh3zuCgsA" # this isn't a secret but you have to look it up
42+
#DATA_SOURCE = "https://www.googleapis.com/youtube/v3/channels/?part=statistics&id=" \
43+
# + CHANNEL_ID +"&key="+settings['youtube_token']
44+
# try also 'viewCount' or 'videoCount
45+
#DATA_LOCATION = ["items", 0, "statistics", "subscriberCount"]
46+
47+
48+
# Subreddit subscribers
49+
#DATA_SOURCE = "https://www.reddit.com/r/circuitpython/about.json"
50+
#DATA_LOCATION = ["data", "subscribers"]
51+
52+
# Hackaday Skulls (likes), requires an API key
53+
#DATA_SOURCE = "https://api.hackaday.io/v1/projects/1340?api_key="+settings['hackaday_token']
54+
#DATA_LOCATION = ["skulls"]
55+
56+
# Twitter followers
57+
#DATA_SOURCE = "https://cdn.syndication.twimg.com/widgets/followbutton/info.json?" + \
58+
#"screen_names=adafruit"
59+
#DATA_LOCATION = [0, "followers_count"]
60+
61+
uart = busio.UART(board.TX, board.RX, timeout=0.1)
62+
resetpin = DigitalInOut(board.D5)
63+
rtspin = DigitalInOut(board.D9)
64+
65+
# Create the connection to the co-processor and reset
66+
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, run_baudrate=921600,
67+
reset_pin=resetpin,
68+
rts_pin=rtspin, debug=True)
69+
esp.hard_reset()
70+
71+
# Create the I2C interface.
72+
i2c = busio.I2C(board.SCL, board.SDA)
73+
# Attach a 7 segment display and display -'s so we know its not live yet
74+
display = segments.Seg7x4(i2c)
75+
display.print('----')
76+
77+
# neopixels
78+
if NEOPIXELS_ON_CHANGE:
79+
pixels = neopixel.NeoPixel(board.A1, 16, brightness=0.4, pixel_order=(1, 0, 2, 3))
80+
pixels.fill(0)
81+
82+
# music!
83+
if PLAY_SOUND_ON_CHANGE:
84+
import audioio
85+
wave_file = open("coin.wav", "rb")
86+
wave = audioio.WaveFile(wave_file)
87+
88+
# we'll save the value in question
89+
last_value = value = None
90+
the_time = None
91+
times = 0
92+
93+
def chime_light():
94+
"""Light up LEDs and play a tune"""
95+
if NEOPIXELS_ON_CHANGE:
96+
for i in range(0, 100, 10):
97+
pixels.fill((i, i, i))
98+
if PLAY_SOUND_ON_CHANGE:
99+
with audioio.AudioOut(board.A0) as audio:
100+
audio.play(wave)
101+
while audio.playing:
102+
pass
103+
if NEOPIXELS_ON_CHANGE:
104+
for i in range(100, 0, -10):
105+
pixels.fill((i, i, i))
106+
pixels.fill(0)
107+
108+
def get_value(response, location):
109+
"""Extract a value from a json object, based on the path in 'location'"""
110+
try:
111+
print("Parsing JSON response...", end='')
112+
json = ujson.loads(response)
113+
print("parsed OK!")
114+
for x in location:
115+
json = json[x]
116+
return json
117+
except ValueError:
118+
print("Failed to parse json, retrying")
119+
return None
120+
121+
while True:
122+
try:
123+
while not esp.is_connected:
124+
# settings dictionary must contain 'ssid' and 'password' at a minimum
125+
esp.connect(settings)
126+
# great, lets get the data
127+
# get the time
128+
the_time = esp.sntp_time
129+
130+
print("Retrieving data source...", end='')
131+
header, body = esp.request_url(DATA_SOURCE)
132+
print("Reply is OK!")
133+
except (RuntimeError, adafruit_espatcontrol.OKError) as e:
134+
print("Failed to get data, retrying\n", e)
135+
continue
136+
#print('-'*40, "Size: ", len(body))
137+
#print(str(body, 'utf-8'))
138+
#print('-'*40)
139+
value = get_value(body, DATA_LOCATION)
140+
if not value:
141+
continue
142+
print(times, the_time, "value:", value)
143+
display.print(int(value))
144+
145+
if last_value != value:
146+
chime_light() # animate the neopixels
147+
last_value = value
148+
times += 1
149+
# normally we wouldn't have to do this, but we get bad fragments
150+
header = body = None
151+
gc.collect()
152+
print(gc.mem_free()) # pylint: disable=no-member
153+
time.sleep(TIME_BETWEEN_QUERY)

examples/espatcontrol_settings.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# This file is where you keep secret settings, passwords, and tokens!
2+
# If you put them in the code you risk committing that info or sharing it
3+
4+
settings = {
5+
'ssid' : 'my access point',
6+
'password' : 'my password',
7+
'timezone' : -5, # this is offset from UTC
8+
'github_token' : 'abcdefghij0123456789',
9+
}

examples/espatcontrol_simpletest.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
1+
import time
12
import board
23
import busio
34
from digitalio import DigitalInOut
45
import adafruit_espatcontrol
56

6-
MY_SSID = "my ssid"
7-
MY_PASSWORD = "the password"
7+
# Get wifi details and more from a settings.py file
8+
try:
9+
from settings import settings
10+
except ImportError:
11+
print("WiFi settings are kept in settings.py, please add them there!")
12+
raise
813

9-
uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=1)
14+
uart = busio.UART(board.TX, board.RX, timeout=0.1)
1015
resetpin = DigitalInOut(board.D5)
1116

1217
print("ESP AT commands")
13-
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, reset_pin=resetpin, debug=False)
18+
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, run_baudrate=9600,
19+
reset_pin=resetpin, debug=False)
20+
print("Resetting ESP module")
21+
esp.hard_reset()
1422

15-
if not esp.soft_reset():
16-
esp.hard_reset()
17-
esp.soft_reset()
18-
19-
esp.echo(False)
20-
print("Connected to AT software version ", esp.get_version())
21-
if esp.mode != esp.MODE_STATION:
22-
esp.mode = esp.MODE_STATION
23-
print("Mode is now", esp.mode)
24-
for ap in esp.scan_APs():
25-
print(ap)
26-
esp.join_AP(MY_SSID, MY_PASSWORD)
27-
print("My IP Address:", esp.local_ip)
23+
while True:
24+
try:
25+
print("Checking connection...")
26+
while not esp.is_connected:
27+
print("Initializing ESP module")
28+
#print("Scanning for AP's")
29+
#for ap in esp.scan_APs():
30+
# print(ap)
31+
# settings dictionary must contain 'ssid' and 'password' at a minimum
32+
print("Connecting...")
33+
esp.connect(settings)
34+
print("Connected to AT software version ", esp.version)
35+
print("Pinging 8.8.8.8...", end="")
36+
print(esp.ping("8.8.8.8"))
37+
time.sleep(10)
38+
except (RuntimeError, adafruit_espatcontrol.OKError) as e:
39+
print("Failed to get data, retrying\n", e)
40+
continue

0 commit comments

Comments
 (0)