├── nqueens.py ├── DHT11_Sensor_SSD1306.py ├── LICENSE ├── SimpleWebClockWithTimer.py ├── WebJSONQuery_Template.py ├── ConwayGameOfLife_SSD1306.py ├── SimpleWebClockWithTimerUsingWebAPI.py ├── DeepSleep_Cloud_Update.py ├── Simple_WebServer_AP.py ├── WS2812_NeoPixelRainbow.py ├── Simple_WebServer.py └── README.md /nqueens.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | maxQueens = 8 4 | 5 | def verifyPos(newColPos, rowPos): 6 | for colPos in range(newColPos): 7 | if queens[colPos] == rowPos or abs(colPos - newColPos) == abs(queens[colPos] - rowPos): 8 | return False 9 | return True 10 | 11 | def placeQueen(maxQ, colPos=0): 12 | global counter 13 | if colPos == maxQ: 14 | counter += 1 15 | print(counter, queens) 16 | else: 17 | for rowPos in range(1, maxQ + 1): 18 | if verifyPos(colPos, rowPos): 19 | queens[colPos] = rowPos 20 | placeQueen(maxQ, colPos + 1) 21 | 22 | counter = 0 23 | queens = [0] * maxQueens 24 | 25 | start = time.ticks_us() 26 | placeQueen(maxQueens) 27 | end = time.ticks_us() 28 | 29 | print('{} results in {} ms'.format(counter, (end - start) / 1000)) 30 | -------------------------------------------------------------------------------- /DHT11_Sensor_SSD1306.py: -------------------------------------------------------------------------------- 1 | # Display DHT11 sensor readings on SSD1306 2 | 3 | from machine import Pin, I2C 4 | import time, dht, ssd1306 5 | 6 | # DHT11 sensor (Pin D5) 7 | dht = dht.DHT11(Pin(14)) 8 | 9 | # SSD1306 OLED display (SCL: D1, SDA: D2) 10 | display = ssd1306.SSD1306_I2C(128, 64, I2C(scl=Pin(5), sda=Pin(4))) 11 | 12 | # template string for formatting 13 | template_str = '\nTemperature:\n {} *C \n\nHumidity:\n {} % ' 14 | 15 | while True: 16 | 17 | # get readings from DHT11 18 | dht.measure() 19 | 20 | # generate formatted string 21 | output_str = template_str.format(dht.temperature(), dht.humidity()) 22 | 23 | # print output without \n (new line) character 24 | print(output_str.replace('\n', '')) 25 | 26 | # print output on oled 27 | display.fill(0) 28 | for index, line in enumerate(output_str.split('\n')): 29 | display.text(line, 8, index * 8) 30 | display.show() 31 | 32 | # wait for 2 seconds 33 | time.sleep(2) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alan Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SimpleWebClockWithTimer.py: -------------------------------------------------------------------------------- 1 | # Timer-based simple clock with SSD1306 oled display (by Alan Wang) 2 | 3 | SSID = '' # WiFi ssid 4 | PW = '' # WiFi password 5 | TMZ_HOUR_OFFSET = 8 # timezone hour offset 6 | SCL = 5 7 | SDA = 4 8 | 9 | import network, ntptime, time, ssd1306, gc 10 | from machine import Pin, SoftI2C, Timer 11 | 12 | gc.enable() 13 | 14 | # weekday names 15 | weekday = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') 16 | 17 | # setup oled display (SCL -> D1, SDA -> D2) 18 | display = ssd1306.SSD1306_I2C(128, 64, SoftI2C(scl=Pin(SCL), sda=Pin(SDA))) 19 | 20 | # setup and connect WiFi 21 | wifi = network.WLAN(network.STA_IF) 22 | wifi.active(True) 23 | wifi.connect(SSID, PW) 24 | while not wifi.isconnected(): 25 | pass 26 | 27 | sec_prev = 0 28 | 29 | # time update function 30 | def ntpUpdate(timer): 31 | while True: 32 | try: 33 | ntptime.settime() # query NTP server and update system time 34 | break 35 | except: 36 | time.sleep(5) # try again if failed 37 | 38 | # display update function 39 | def clockUpdate(timer): 40 | global sec_prev 41 | lt = time.localtime(time.time() + TMZ_HOUR_OFFSET * 3600) 42 | if lt[5] != sec_prev: 43 | display.fill(0) 44 | display.text(weekday[lt[6]], 8, 8) 45 | display.text('{0:04d}-{1:02d}-{2:02d}'.format(*lt), 8, 24) 46 | display.text('{3:02d}:{4:02d}:{5:02d}'.format(*lt), 8, 40) 47 | display.show() # display clock 48 | sec_prev = lt[5] 49 | 50 | # update time for the first time 51 | ntpUpdate(None) 52 | 53 | # start timers (coroutines) 54 | timer_ntp, timer_display = Timer(-1), Timer(-1) 55 | timer_ntp.init(mode=Timer.PERIODIC, period=900000, callback=ntpUpdate) 56 | timer_display.init(mode=Timer.PERIODIC, period=100, callback=clockUpdate) 57 | -------------------------------------------------------------------------------- /WebJSONQuery_Template.py: -------------------------------------------------------------------------------- 1 | # ESP8266 Web JSON Query Template 2 | 3 | import network, requests, time, sys 4 | 5 | # user info 6 | ssid = '' # change this to your WiFi AP name 7 | pw = '' # change this to your WiFi AP password 8 | 9 | # API url 10 | api_url = 'http://api.open-notify.org/iss-now.json' 11 | 12 | 13 | # wifi error descriptions 14 | wifi_error = { 15 | network.STAT_WRONG_PASSWORD: 'wrong password', 16 | network.STAT_NO_AP_FOUND: 'wifi AP not found', 17 | -1: 'due to other problems', 18 | } 19 | 20 | # connecting to WiFi 21 | wifi = network.WLAN(network.STA_IF) 22 | wifi.active(True) 23 | wifi.connect(ssid, pw) 24 | 25 | print('ESP8266 connecting to', ssid, '...') 26 | while wifi.status() == network.STAT_CONNECTING: 27 | pass 28 | 29 | if wifi.status() != network.STAT_GOT_IP: 30 | print('Failed to connect:', wifi_error.get(wifi.status(), wifi_error[-1])) 31 | sys.exit() 32 | 33 | print('Connected.') 34 | print('IP:', wifi.ifconfig()[0], '\n') 35 | time.sleep(1) 36 | 37 | 38 | while True: 39 | 40 | try: 41 | # send HTTP GET request to the API 42 | print('Querying API:', api_url) 43 | response = requests.get(api_url) 44 | 45 | if response.status_code == 200: 46 | print('Query successful. JSON response:') 47 | # return a dict object containing the JSON data 48 | parsed = response.json() 49 | print(parsed) # you can access data by using parsed[key] 50 | 51 | else: 52 | print('Query failed. ' + \ 53 | 'Status code:', response.status_code) 54 | 55 | response.close() 56 | 57 | except Exception as e: 58 | print('Error occurred:', e) 59 | print('If you see a SSL error above, ' + \ 60 | 'either you have unstable Wifi or ' + \ 61 | 'the API is not supported by MicroPython.') 62 | 63 | print('') 64 | time.sleep(30) 65 | -------------------------------------------------------------------------------- /ConwayGameOfLife_SSD1306.py: -------------------------------------------------------------------------------- 1 | # Conway's Game of Life on 128x64 SSD1306 OLED and ESP8266 (by Alan Wang) 2 | 3 | 4 | BIRTH = (3, ) # number of nearby cells for a new cell to be born 5 | SURVIVAL = (2, 3) # number of nearby cells for an existing cell to survive 6 | WIDTH = 128 7 | HEIGHT = 64 8 | DOT_SIZE = 3 # draw 3x3 dots -> board size 128/3 x 64/3 9 | RAND_BIT = 2 # cell randomize factor (2 = 2^2 (1/4 chance)) 10 | 11 | 12 | from machine import Pin, ADC, SoftI2C, freq 13 | from micropython import const 14 | from ssd1306 import SSD1306_I2C 15 | import random, time, gc 16 | 17 | 18 | freq(160000000) 19 | gc.enable() 20 | random.seed(sum([ADC(0).read() for _ in range(1000)])) # generate randomize seed from floating analog pin 21 | 22 | 23 | X = WIDTH // DOT_SIZE 24 | Y = HEIGHT // DOT_SIZE 25 | TOTAL = X * Y 26 | board = [0 if random.getrandbits(RAND_BIT) else 1 27 | for _ in range(TOTAL)] 28 | gen = 0 29 | 30 | 31 | display = SSD1306_I2C(WIDTH, HEIGHT, 32 | SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)) 33 | display.fill(0) 34 | display.show() 35 | 36 | 37 | print('Conway\'s Game of Life: matrix size {} x {}'.format(X, Y)) 38 | 39 | 40 | def calculate_next_gen(): # calculate next generation of cells 41 | global board 42 | buffer = [0] * TOTAL 43 | for i in range(TOTAL): 44 | group = board[i-1:i+2] + \ 45 | board[(i-1-X)%TOTAL:(i+2-X)%TOTAL] + \ 46 | board[(i-1+X)%TOTAL:(i+2+X)%TOTAL] 47 | cells = sum(group) 48 | if not board[i]: 49 | if cells in BIRTH: 50 | buffer[i] = 1 51 | else: 52 | if (cells - 1) in SURVIVAL: 53 | buffer[i] = 1 54 | board = buffer 55 | 56 | 57 | def display_board(): # draw cells on OLED 58 | display.fill(0) 59 | for i in range(TOTAL): 60 | if board[i]: 61 | display.fill_rect((i % X) * DOT_SIZE, 62 | (i // X) * DOT_SIZE, 63 | DOT_SIZE, DOT_SIZE, 1) 64 | display.show() 65 | 66 | 67 | gen, t_start, t_dur = 0, 0, 0 68 | 69 | while True: 70 | gen += 1 71 | print('Gen {}: {} cell(s) ({} ms)'.format(gen, sum(board), t_dur)) 72 | display_board() 73 | t_start = time.ticks_ms() 74 | calculate_next_gen() 75 | t_dur = time.ticks_diff(time.ticks_ms(), t_start) 76 | -------------------------------------------------------------------------------- /SimpleWebClockWithTimerUsingWebAPI.py: -------------------------------------------------------------------------------- 1 | # Timer-based clock with SSD1306 oled display (by Alan Wang), 2 | # RTC and World Time API version (automatic timezone) 3 | 4 | SSID = '' # WiFi ssid 5 | PW = '' # WiFi password 6 | SCL = 5 7 | SDA = 4 8 | 9 | import network, requests, time, ssd1306, gc 10 | from machine import Pin, SoftI2C, Timer, RTC 11 | 12 | gc.enable() 13 | 14 | # weekday names 15 | weekday = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') 16 | 17 | # setup oled display (SCL -> D1, SDA -> D2) 18 | display = ssd1306.SSD1306_I2C(128, 64, SoftI2C(scl=Pin(SCL), sda=Pin(SDA))) 19 | 20 | # inernal RTC 21 | rtc = RTC() 22 | 23 | # setup and connect WiFi 24 | wifi = network.WLAN(network.STA_IF) 25 | wifi.active(True) 26 | wifi.connect(SSID, PW) 27 | while not wifi.isconnected(): 28 | pass 29 | 30 | sec_prev = 0 31 | 32 | # time update function 33 | def rtcUpdate(timer): 34 | while True: 35 | try: 36 | response = requests.get('http://worldtimeapi.org/api/ip') 37 | if response.status_code == 200: 38 | parsed = response.json() 39 | # parsed['unixtime']: local unixtime since 1970/01/01 00:00:00) 40 | # parsed['raw_offset']: timezone hour offset 41 | # 946684800: unixtime of 2020/01/01 00:00:00 (system start time on MicroPython) 42 | # generate datetime tuple based on these information 43 | dt = time.localtime(parsed['unixtime'] + parsed['raw_offset'] - 946684800) 44 | # rtc.datetime((year, month, day, weekday, hour, minute, second, microsecond)) 45 | rtc.datetime((dt[0], dt[1], dt[2], dt[6], dt[3], dt[4], dt[5], 0)) 46 | break 47 | except: 48 | time.sleep(10) # try again if failed 49 | 50 | # display update function 51 | def clockUpdate(timer): 52 | global sec_prev 53 | dt = rtc.datetime() 54 | if dt[6] != sec_prev: 55 | display.fill(0) 56 | display.text(weekday[dt[3]], 8, 8) 57 | display.text('{0:04d}-{1:02d}-{2:02d}'.format(*dt), 8, 24) 58 | display.text('{4:02d}:{5:02d}:{6:02d}'.format(*dt), 8, 40) 59 | display.show() # display clock 60 | sec_prev = dt[6] 61 | 62 | # update time for the first time 63 | rtcUpdate(None) 64 | 65 | # start timers 66 | timer_ntp, timer_display = Timer(-1), Timer(-1) 67 | timer_ntp.init(mode=Timer.PERIODIC, period=900000, callback=rtcUpdate) 68 | timer_display.init(mode=Timer.PERIODIC, period=100, callback=clockUpdate) 69 | -------------------------------------------------------------------------------- /DeepSleep_Cloud_Update.py: -------------------------------------------------------------------------------- 1 | # ESP8266 Deep Sleep/Cloud Data Update 2 | 3 | # Upload this script onto the board as main.py, then remember to 4 | # connect D0 (GPIO 16) and RST with a jumper wire in order to 5 | # wake the board from deep sleep. 6 | 7 | # You can also maunally wake it up by pressing the RST button or 8 | # pull RST low with an external switch. 9 | 10 | # Afterwards, you may need to re-flash the firmware to reset ESP8266. 11 | 12 | import network, requests, machine, time, dht 13 | 14 | # user info 15 | wifi_ssid = 'your_wifi_ssid' # change this to your WiFi AP name 16 | wifi_pw = 'your_wifi_password' # change this to your WiFi AP password 17 | 18 | # IFTTT Webhook key/event name 19 | # see: https://ifttt.com/maker_webhooks 20 | webhook_key = 'your_ifttt_webhook_key' 21 | webhook_event_name = 'your_ifttt_webhook_event_name' 22 | 23 | webhook_url = 'https://maker.ifttt.com/trigger/' + \ 24 | webhook_event_name + '/with/key/' + webhook_key 25 | 26 | 27 | if machine.reset_cause() == machine.DEEPSLEEP_RESET: 28 | print('ESP8266 woken from a deep sleep...') 29 | 30 | 31 | # light up onboard LED 32 | led = machine.Pin(2, machine.Pin.OUT, value=0) 33 | 34 | 35 | # connecting to WiFi 36 | wifi = network.WLAN(network.STA_IF) 37 | wifi.active(True) 38 | 39 | wifi.connect(wifi_ssid, wifi_pw) 40 | while not wifi.isconnected(): 41 | pass 42 | 43 | 44 | # get readings from DHT11 (connected to D5) 45 | dht = dht.DHT11(machine.Pin(14)) 46 | dht.measure() 47 | 48 | 49 | # Upload data via IFTTT 50 | query_url = '{}?value1={}&value2={}&value3={}'.format( 51 | webhook_url, 'Temp(*C)/Humid(%)', 52 | dht.temperature(), dht.humidity()) 53 | 54 | response = None 55 | 56 | try: 57 | print('Upload data...') 58 | response = requests.get(query_url) 59 | except: 60 | pass 61 | 62 | if not response == None and response.status_code == 200: 63 | print('Upload successful') 64 | # led flashing quickly 65 | for _ in range(10): 66 | led.value(1) 67 | time.sleep_ms(25) 68 | led.value(0) 69 | time.sleep_ms(25) 70 | else: 71 | print('Upload failed') 72 | # led flashing slowly 73 | led.value(1) 74 | time.sleep_ms(250) 75 | led.value(0) 76 | time.sleep_ms(250) 77 | 78 | # led off 79 | led.value(1) 80 | 81 | 82 | # Go to deep sleep and wake up after a period of time 83 | print('Go to deep sleep...') 84 | rtc = machine.RTC() 85 | rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) 86 | rtc.alarm(rtc.ALARM0, 30000) 87 | machine.deepsleep() 88 | -------------------------------------------------------------------------------- /Simple_WebServer_AP.py: -------------------------------------------------------------------------------- 1 | ssid = 'ESP8266' # AP name 2 | pw = '12345678' # AP password 3 | port = 80 # server port 4 | conns = 1 # number of channels 5 | 6 | 7 | from machine import Pin 8 | import network, socket 9 | 10 | led = Pin(2, Pin.OUT, value=1) 11 | 12 | 13 | # webpage template 14 | html = """ 15 | 16 | 17 |
18 |