--- /dev/null
+# ignore secrets files
+secrets.py
+secrets.json
--- /dev/null
+from machine import Pin
+from neopixel import NeoPixel
+import time
+
+# Definitions for the ATOM Matrix
+LED_GPIO = const(27)
+matrix_size_x = const(5)
+matrix_size_y = const(5)
+is_atom_matrix = True
+
+np = NeoPixel(Pin(LED_GPIO), matrix_size_x * matrix_size_y)
+
+while True:
+ np.fill((175,50,0))
+ np.write()
+ time.sleep(0.5)
+ np.fill((175,25,0))
+ np.write()
+ time.sleep(0.5)
+ np.fill((175,0,5))
+ np.write()
+ time.sleep(0.5)
+ np.fill((150,0,25))
+ np.write()
+ time.sleep(0.5)
+ np.fill((100,0,75))
+ np.write()
+ time.sleep(0.5)
+ np.fill((50,0,100))
+ np.write()
+ time.sleep(0.5)
+ np.fill((50,0,150))
+ np.write()
+ time.sleep(0.5)
+ np.fill((25,0,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((0,25,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((0,50,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((0,75,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((0,150,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((0,175,175))
+ np.write()
+ time.sleep(0.5)
+ np.fill((5,150,100))
+ np.write()
+ time.sleep(0.5)
+ np.fill((50,75,0))
+ np.write()
+ time.sleep(0.5)
+ np.fill((100,50,0))
+ np.write()
+ time.sleep(0.5)
+ np.fill((150,50,0))
+ np.write()
+ time.sleep(0.5)
--- /dev/null
+# This file is executed on every boot (including wake-boot from deepsleep)
+#import esp
+#esp.osdebug(None)
+#import webrepl
+#webrepl.start()
+import network, ujson
+wlan=network.WLAN(network.STA_IF)
+wlan.active(True)
+
+def readSecrets():
+ with open('secrets.json') as fp:
+ secrets=ujson.loads(fp.read())
+ return secrets
+
+def wifiConnect():
+ secrets=readSecrets()
+ wlan.connect(secrets['phone_wifi']['ssid'],secrets['phone_wifi']['pass'])
+
+wifiConnect()
\ No newline at end of file
--- /dev/null
+from mpu6886 import MPU6886
+from neopixel import NeoPixel
+from machine import Pin, SoftI2C
+from time import sleep
+from math import *
+
+# Definitions for the ATOM Matrix
+LED_GPIO = const(27)
+MPU6886_SCL = const(21)
+MPU6886_SDA = const(25)
+matrix_size_x = const(5)
+matrix_size_y = const(5)
+is_atom_matrix = True
+
+# Definitions for the M5StickC + NeoFlash hat
+#LED_GPIO = const(26)
+#MPU6886_SCL = const(22)
+#MPU6886_SDA = const(21)
+#matrix_size_x = const(18)
+#matrix_size_y = const(7)
+#is_atom_matrix = False
+
+threshold = const(5) # minimum angle that triggers movement
+color = (0, 0, 20) # Initial color: Blue
+x = int(matrix_size_x / 2) # Get matrix
+y = int(matrix_size_y / 2) # center
+np = NeoPixel(Pin(LED_GPIO), matrix_size_x * matrix_size_y)
+
+def computeAngles(ax,ay,az):
+ # https://roboticsclubiitk.github.io/2017/12/21/Beginners-Guide-to-IMU.html
+ pitch = 180 * atan (ax/sqrt(ay**2 + az**2))/ pi
+ roll = 180 * atan (ay/sqrt(ax**2 + az**2))/ pi
+ yaw = 180 * atan (az/sqrt(ax**2 + ay**2))/ pi
+ return pitch, roll, yaw
+
+def updateDot(p, angle, size, threshold, color1, color2):
+ global color
+ if angle > threshold: # Test if angle is positive
+ if p < size - 1: # If it is not at the matrix
+ p = p + 1 # border, move the dot
+ else:
+ color = color1 # change color if reached the border
+ elif angle < - threshold: # Test if angle is negative
+ if p > 0: # If it is not at the matrix
+ p = p - 1 # border, move the dot
+ else:
+ color = color2 # change color if reached the border
+ return p
+
+# I2C bus init for MPU6886
+i2c = SoftI2C(scl=Pin(MPU6886_SCL), sda=Pin(MPU6886_SDA))
+
+# Values you can use to initialize the accelerometer. AFS_16G, means +-8G sensitivity, and so on
+# Larger scale means less precision
+AFS_2G = const(0x00)
+AFS_4G = const(0x01)
+AFS_8G = const(0x02)
+AFS_16G = const(0x03)
+
+# Values you can use to initialize the gyroscope. GFS_2000DPS means 2000 degrees per second sensitivity, and so on
+# Larger scale means less precision
+GFS_250DPS = const(0x00)
+GFS_500DPS = const(0x01)
+GFS_1000DPS = const(0x02)
+GFS_2000DPS = const(0x03)
+
+# by default, if you initialize MPU6886 with imu = MPU6886(i2c), GFS_2000DPS and AFS_8G are used
+# if you want to initialize with other values you have too use :
+# imu = MPU6886(i2c,mpu6886.GFS_250DPS,mpu6886.AFS_4G )
+# imu = MPU6886(i2c) #=> use default 8G / 2000DPS
+imu = MPU6886(i2c, GFS_500DPS, AFS_4G)
+
+# in order to calibrate Gyroscope you have to put the device on a flat surface
+# preferably level with the floor and not touch it during the procedure. (1s for 20 cycles)
+#calibrateGyro(20)
+
+while True:
+ ax,ay,az = imu.getAccelData()
+# gx,gy,gz = imu.getGyroData()
+ pitch, roll, yaw = computeAngles(ax,ay,az)
+# print(ax,ay,az)
+# print(pitch, roll, yaw)
+ np[ y * matrix_size_x + x ] = (0,0,0) # Turn off the LED on the current dot possition
+ if is_atom_matrix:
+ x = updateDot(x, pitch, matrix_size_x, threshold, (20, 0, 0), (20, 20, 0))
+ y = updateDot(y, roll, matrix_size_y, threshold, (20, 0, 20), (0, 20, 20))
+ else: # Compensate for the different orientation of the sensor on the M5StickC
+ x = updateDot(x, -roll, matrix_size_x, threshold, (20, 0, 0), (20, 20, 0))
+ y = updateDot(y, pitch, matrix_size_y, threshold, (20, 0, 20), (0, 20, 20))
+ np[ y * matrix_size_x + x ] = color # Turn on the LED on the new dot possition
+ np.write()
+ sleep(0.2)
\ No newline at end of file
--- /dev/null
+import network, socket, time
+from neopixel import NeoPixel
+from machine import Pin
+
+LED_GPIO = const(27)
+matrix_size_x = const(5)
+matrix_size_y = const(5)
+is_atom_matrix = True
+
+np = NeoPixel(Pin(LED_GPIO), matrix_size_x * matrix_size_y)
+
+ssid=[SSID]
+password=[PASSWORD]
+
+def connect():
+ wlan=network.WLAN(network.STA_IF)
+ wlan.active(True)
+ wlan.connect(ssid,password)
+ while wlan.isconnected() == False:
+ print('Waiting for connection...')
+ time.sleep(1)
+ ip=wlan.ifconfig()[0]
+ print(f'Connected on {ip}')
+ return ip
+
+def open_socket(ip):
+ address=(ip,80)
+ connection=socket.socket()
+ connection.bind(address)
+ connection.listen(1)
+ return connection
+
+def get_html(html_name):
+ with open(html_name, 'r') as file:
+ html=file.read()
+ return html
+
+def serve(connection):
--- /dev/null
+# C.LEBOCQ 02/2020
+# MicroPython library for the MPU6886 imu ( M5StickC / ATOM Matrix )
+# Based on https://github.com/m5stack/M5StickC/blob/master/src/utility/MPU6886.cpp
+
+from machine import I2C
+from time import sleep
+
+MPU6886_ADDRESS = const(0x68)
+MPU6886_WHOAMI = const(0x75)
+MPU6886_ACCEL_INTEL_CTRL = const(0x69)
+MPU6886_SMPLRT_DIV = const(0x19)
+MPU6886_INT_PIN_CFG = const(0x37)
+MPU6886_INT_ENABLE = const(0x38)
+MPU6886_ACCEL_XOUT_H = const(0x3B)
+MPU6886_ACCEL_XOUT_L = const(0x3C)
+MPU6886_ACCEL_YOUT_H = const(0x3D)
+MPU6886_ACCEL_YOUT_L = const(0x3E)
+MPU6886_ACCEL_ZOUT_H = const(0x3F)
+MPU6886_ACCEL_ZOUT_L = const(0x40)
+
+MPU6886_TEMP_OUT_H = const(0x41)
+MPU6886_TEMP_OUT_L = const(0x42)
+
+MPU6886_GYRO_XOUT_H = const(0x43)
+MPU6886_GYRO_XOUT_L = const(0x44)
+MPU6886_GYRO_YOUT_H = const(0x45)
+MPU6886_GYRO_YOUT_L = const(0x46)
+MPU6886_GYRO_ZOUT_H = const(0x47)
+MPU6886_GYRO_ZOUT_L = const(0x48)
+
+MPU6886_USER_CTRL = const(0x6A)
+MPU6886_PWR_MGMT_1 = const(0x6B)
+MPU6886_PWR_MGMT_2 = const(0x6C)
+MPU6886_CONFIG = const(0x1A)
+MPU6886_GYRO_CONFIG = const(0x1B)
+MPU6886_ACCEL_CONFIG = const(0x1C)
+MPU6886_ACCEL_CONFIG2 = const(0x1D)
+MPU6886_FIFO_EN = const(0x23)
+
+#consts for Acceleration & Resolution scale
+AFS_2G = const(0x00)
+AFS_4G = const(0x01)
+AFS_8G = const(0x02)
+AFS_16G = const(0x03)
+
+GFS_250DPS = const(0x00)
+GFS_500DPS = const(0x01)
+GFS_1000DPS = const(0x02)
+GFS_2000DPS = const(0x03)
+
+class MPU6886():
+
+ def __init__(self, i2c, Gscale = GFS_2000DPS, Ascale = AFS_8G):
+ self.i2c = i2c
+ self.Gscale = Gscale
+ self.Ascale = Ascale
+ if self.init():
+ self.setAccelFsr(Ascale)
+ self.setGyroFsr(Gscale)
+
+ # sleep in ms
+ def sleepms(self,n):
+ sleep(n / 1000)
+
+ # set I2C reg (1 byte)
+ def setReg(self, reg, dat):
+ self.i2c.writeto(MPU6886_ADDRESS, bytearray([reg, dat]))
+
+ # get I2C reg (1 byte)
+ def getReg(self, reg):
+ self.i2c.writeto(MPU6886_ADDRESS, bytearray([reg]))
+ t = self.i2c.readfrom(MPU6886_ADDRESS, 1)
+ return t[0]
+
+ # get n reg
+ def getnReg(self, reg, n):
+ self.i2c.writeto(MPU6886_ADDRESS, bytearray([reg]))
+ t = self.i2c.readfrom(MPU6886_ADDRESS, n)
+ return t
+
+ def init(self):
+ tempdata = self.getReg(MPU6886_WHOAMI)
+ if tempdata != 0x19:
+ return False
+ self.sleepms(1)
+ regdata = 0x00
+ self.setReg(MPU6886_PWR_MGMT_1, regdata)
+ self.sleepms(10)
+ regdata = (0x01<<7)
+ self.setReg(MPU6886_PWR_MGMT_1, regdata)
+ self.sleepms(10)
+ regdata = (0x01<<0)
+ self.setReg(MPU6886_PWR_MGMT_1, regdata)
+ self.sleepms(10)
+ regdata = 0x10
+ self.setReg(MPU6886_ACCEL_CONFIG, regdata)
+ self.sleepms(1)
+ regdata = 0x18
+ self.setReg(MPU6886_GYRO_CONFIG, regdata)
+ self.sleepms(1)
+ regdata = 0x01
+ self.setReg(MPU6886_CONFIG, regdata)
+ self.sleepms(1)
+ regdata = 0x05
+ self.setReg(MPU6886_SMPLRT_DIV, regdata)
+ self.sleepms(1)
+ regdata = 0x00
+ self.setReg(MPU6886_INT_ENABLE, regdata)
+ self.sleepms(1)
+ regdata = 0x00
+ self.setReg(MPU6886_ACCEL_CONFIG2, regdata)
+ self.sleepms(1)
+ regdata = 0x00
+ self.setReg(MPU6886_USER_CTRL, regdata)
+ self.sleepms(1)
+ regdata = 0x00
+ self.setReg(MPU6886_FIFO_EN, regdata)
+ self.sleepms(1)
+ regdata = 0x22
+ self.setReg(MPU6886_INT_PIN_CFG, regdata)
+ self.sleepms(1)
+ regdata = 0x01
+ self.setReg(MPU6886_INT_ENABLE, regdata)
+ self.sleepms(100)
+ self.getGres()
+ self.getAres()
+ return True
+
+ def getGres(self):
+ if self.Gscale == GFS_250DPS:
+ self.gRes = 250.0 / 32768.0
+ elif self.Gscale == GFS_500DPS:
+ self.gRes = 500.0/32768.0
+ elif self.Gscale == GFS_1000DPS:
+ self.gRes = 1000.0/32768.0
+ elif self.Gscale == GFS_2000DPS:
+ self.gRes = 2000.0/32768.0
+ else:
+ self.gRes = 250.0/32768.0
+
+ def getAres(self):
+ if self.Ascale == AFS_2G:
+ self.aRes = 2.0/32768.0
+ elif self.Ascale == AFS_4G:
+ self.aRes = 4.0/32768.0
+ elif self.Ascale == AFS_8G:
+ self.aRes = 8.0/32768.0
+ elif self.Ascale == AFS_16G:
+ self.aRes = 16.0/32768.0
+ else:
+ self.aRes = 2.0/32768.0
+
+ def getAccelAdc(self):
+ buf = self.getnReg(MPU6886_ACCEL_XOUT_H,6)
+
+ ax = (buf[0]<<8) | buf[1]
+ ay = (buf[2]<<8) | buf[3]
+ az = (buf[4]<<8) | buf[5]
+ return ax,ay,az
+
+ def getAccelData(self):
+ ax,ay,az = self.getAccelAdc()
+ if ax > 32768:
+ ax -= 65536
+ if ay > 32768:
+ ay -= 65536
+ if az > 32768:
+ az -= 65536
+ ax *= self.aRes
+ ay *= self.aRes
+ az *= self.aRes
+ return ax,ay,az
+
+ def getGyroAdc(self):
+ buf = self.getnReg(MPU6886_GYRO_XOUT_H,6)
+ gx = (buf[0]<<8) | buf[1]
+ gy = (buf[2]<<8) | buf[3]
+ gz = (buf[4]<<8) | buf[5]
+ return gx,gy,gz
+
+ def getGyroData(self):
+ gx,gy,gz = self.getGyroAdc()
+ if gx > 32768:
+ gx -= 65536
+ if gy > 32768:
+ gy -= 65536
+ if gz > 32768:
+ gz -= 65536
+ gx *= self.gRes
+ gy *= self.gRes
+ gz *= self.gRes
+ return gx, gy, gz
+
+ def getTempAdc(self):
+ buf = self.getnReg(MPU6886_TEMP_OUT_H,2)
+ return (buf[0]<<8) | buf[1]
+
+ def getTempData(self):
+ return self.getTempAdc() / 326.8 + 25.0
+
+ def setGyroFsr(self,scale):
+ regdata = (scale<<3)
+ self.setReg(MPU6886_GYRO_CONFIG, regdata)
+ self.sleepms(10)
+ self.Gscale = scale
+ self.getGres()
+
+ def setAccelFsr(self,scale):
+ regdata = (scale<<3)
+ self.setReg(MPU6886_ACCEL_CONFIG, regdata)
+ self.sleepms(10)
+ self.Ascale = scale
+ self.getAres()
\ No newline at end of file
--- /dev/null
+from machine import Pin
+from neopixel import NeoPixel
+import time
+
+# Definitions for the ATOM Matrix
+LED_GPIO = const(27)
+matrix_size_x = const(5)
+matrix_size_y = const(5)
+is_atom_matrix = True
+
+np = NeoPixel(Pin(LED_GPIO), matrix_size_x * matrix_size_y)
+n=25
+def wheel(pos):
+ if pos < 0 or pos > 255:
+ return (0, 0, 0)
+ if pos < 85:
+ return (255 - pos * 3, pos * 3, 0)
+ if pos < 170:
+ pos -= 85
+ return (0, 255 - pos * 3, pos * 3)
+ pos -= 170
+ return (pos * 3, 0, 255 - pos * 3)
+
+def rainbow_cycle(wait):
+ for j in range(255):
+ for i in range(n):
+ rc_index = (i * 256 // n) + j
+ np.fill(wheel(rc_index & 255))
+ np.write()
+ time.sleep_ms(wait)
+
+while True:
+ rainbow_cycle(30)
\ No newline at end of file