提交 e53eeb2c 编写于 作者: W wzhiyuan-nit 提交者: skylarCai

BugID:1761:Add the source code of weight scale.

[Detail]
Issue description:

Rootcause:

Solution:

Requirement description:

Solution:

[Verified Cases]
Build Pass: <solution list>
Test Pass: <test case list>
Signed-off-by: Nwzhiyuan-nit <wuming.wzy@alibaba-inc.com>
上级 662af021
# 体重秤
## 简介
&emsp;&emsp;
此案例设计的体重秤是一种可以自动连接阿里云的智能称重设备,您可以通过手机端应用查看体重数据。在设定身高后,还可查看自己的体重指数,以及系统根据体重指数向您推送的健康建议。
## 准备
&emsp;&emsp;
硬件列表
* Haas EDU K1开发板一个
* HX711电子秤传感器一个
* 杜邦连接线若干
Haas EDU K1开发板与转接板、步进电机及电子秤传感器之间的硬件连线
<table>
<tr>
<td align="center">硬件</td>
<td align="center">HX711电子秤传感器</td>
<td align="center">Haas EDU K1开发板</td>
</tr>
<tr>
<td align="center" rowspan="4">端口标识</td>
<td align="center">GND</td>
<td align="center">GND</td>
</tr>
<tr>
<td align="center">VCC</td>
<td align="center">3.3V</td>
</tr>
<tr>
<td align="center">SCK</td>
<td align="center">P02</td>
</tr>
<tr>
<td align="center">DT</td>
<td align="center">P03</td>
</tr>
<tr>
<td align="center" rowspan="1">硬件说明</td>
<td align="center" >-</td>
<td> <a align="center" href="https://haas.iot.aliyun.com/solution/detail/hardware?versionId=800C5AB3B8A4A88800000001&dataId=800C5AB3B8A4A888" target="_blank">快速开始详细端口定义</td>
</tr>
</table>
### 硬件连线图
&emsp;&emsp;
硬件连线图如下所示:
![体重秤_接线示意图.png](./../../../images/weight_scale/体重秤_接线示意图.png)
![体重秤_连线图.png](./../../../images/weight_scale/体重秤_连线图.png)
## 物联网平台开发
&emsp;&emsp;
整个过程包含以下4个步骤:
1. 开通公共实例
2. 创建产品(设备模型)
3. 定义产品功能(物模型)
4. 创建设备及获取三元组
### 开通公共实例
&emsp;&emsp;
对于第一次使用物联网平台的读者,需要开通实例以使用物联网平台的功能。这里可以使用免费的公共实例进行开发。
&emsp;&emsp;
[物联网平台](https://iot.console.aliyun.com/lk/summary/new)中,左上角选择“华东2-上海”,点击“公共实例”,即可开通。开通后点击“公共实例”,即可进入[控制台](https://iot.console.aliyun.com/lk/summary/new)进行产品创建。
![体重秤_物联网平台.png](./../../../images/weight_scale/体重秤_物联网平台.png)
### 创建产品(设备模型)
&emsp;&emsp;
进入[公共实例控制台](https://iot.console.aliyun.com/lk/summary/new),点击“创建产品”按钮,即可进入[新建产品页面](https://iot.console.aliyun.com/product)
![体重秤_空产品页.png](./../../../images/weight_scale/体重秤_空产品页.png)
&emsp;&emsp;
进入[新建产品页面](https://iot.console.aliyun.com/product),设定“产品名称”,这里我们命名为“**体重秤**”,读者也可以根据自己的喜好来命名。在“所属品类”中,选择“自定义品类”。
&emsp;&emsp;
产品的节点类型选择“直连设备”,数据格式选择“ICA标准数据格式”,检验类型和认证方式选择默认设定即可。开发者可根据自己的需求在“产品描述”页面添加针对此产品的描述。
&emsp;&emsp;
对于搭载 Wi-Fi 的设备而言,联网方式选择“Wi-Fi”。
![体重秤_新建产品.png](./../../../images/weight_scale/体重秤_新建产品.png)
&emsp;&emsp;
点击“确认”按钮,即可完成产品创建。
![体重秤_完成创建产品.png](./../../../images/weight_scale/体重秤_完成创建产品.png)
&emsp;&emsp;
点击“前往定义物模型”
![体重秤_尚未添加任何功能.png](./../../../images/weight_scale/体重秤_尚未添加任何功能.png)
### 定义产品功能(物模型)
&emsp;&emsp;
进入功能定义,点击编辑草稿,选择添加自定义功能,依次添加“体重”“健康状态”“体重指数”“健康建议”“身高”五个功能项,如下所示:
![体重秤_导入完成.png](./../../../images/weight_scale/体重秤_创建物模型.png)
&emsp;&emsp;
定义好物模型后,需要发布物模型上线,并发布产品,以使变更生效。
![体重秤_发布物模型.png](./../../../images/weight_scale/体重秤_发布物模型.png)
![体重秤_发布产品.png](./../../../images/weight_scale/体重秤_发布产品.png)
&emsp;&emsp;
产品及其物模型创建完成后就可以创建这个产品的设备了。
### 创建设备及获取三元组
&emsp;&emsp;
点击左侧栏中“设备“,在筛选框中选择要添加设备的产品,点击“添加设备”。这里这里我们命名为“**weight_scale**”,开发者也可以根据自己的喜好来命名。
![体重秤_添加设备.png](./../../../images/weight_scale/体重秤_添加设备.png)
&emsp;&emsp;
开发者也可以选择“批量添加”,一次性添加多个设备,并生成随机的DeviceName。
![体重秤_批量添加.png](./../../../images/weight_scale/体重秤_批量添加.png)
&emsp;&emsp;
生成的设备如下。
![体重秤_设备列表.png](./../../../images/weight_scale/体重秤_设备列表.png)
&emsp;&emsp;
点击前往“查看”按钮,就可以看到此设备的详细信息了。
![体重秤_设备详情.png](./../../../images/weight_scale/体重秤_设备详情.png)
&emsp;&emsp;
点击右上角的“查看”按钮,就能看到设备的三元组信息了。三元组是物联网设备端和物联网云端设备相关联的唯一标识符,在设备端连接云端的时候会使用三元组信息和云端进行鉴权,鉴权通过之后云端会认为设备已激活并上线。
![体重秤_设备证书.png](./../../../images/weight_scale/体重秤_设备证书.png)
&emsp;&emsp;
再次前往物联网平台的设备信息页面,若设备运行正确,此时应该可以看到设备名右侧的状态由“未激活”变为“在线”。
选中“实时刷新”,可以看到数据实时从设备上报到物联网平台。设备上云成功。
![体重秤_物模型数据.png](./../../../images/weight_scale/体重秤_物模型数据.png)
## 设备端开发
### 开发环境
&emsp;&emsp;
在进行下一步之前请确保HaaS EDU K1开发环境已经搭建完毕。详情请参考[HaaS EDU K1开发环境](https://haas.iot.aliyun.com/haasapi/index.html?spm=a2cpu.b16145223.0.0.665960b1PR2nSt#/Python/docs/zh-CN/startup/HaaS_EDU_K1_startup)的说明。
### 创建解决方案
&emsp;&emsp;
如下图所示,在Haas Studio中新建一个helloworld的python工程,开发板选择“HaaS EDU k1”。设定好工程名称(“weight_scale”)及工作区路径之后,点击确定。
![体重秤_创建工程](./../../../images/weight_scale/体重秤_创建工程.png)
&emsp;&emsp;
[全部代码](./code/)文件复制并覆盖刚刚创建的工程目录下的原有文件,之后对代码进行如下修改。
1. **填写Wi-Fi名称及密码**
&emsp;&emsp;
在main.py中,填写可用的Wi-Fi名称及密码。
``` python
# wifi连接的的ssid和pwd定义
wifi_ssid = "请填写您的路由器名称"
wifi_password = "请填写您的路由器密码"
```
2. **修改设备端三元组**
&emsp;&emsp;
在main.py中,填写创建的设备三元组信息。关于设备三元组的获取,请参考[创建设备及获取三元组](./README.md "创建设备及获取三元组")中的步骤。
``` python
# 三元组信息
productKey = "产品key"
deviceName = "设备名称"
deviceSecret = "设备密钥"
```
## 物联网应用开发
&emsp;&emsp;
IoT Studio 提供了应用快速开发的能力,可以很方便地与物联网平台进行联动。本节的开发工作也将围绕 IoT Studio展开。
### 新建“普通项目”
&emsp;&emsp;
打开IoT Studio官网,在项目管理中新建一个空白项目,如下图所示,将此项目命名为“**体重秤**”,开发者也可以根据自己的喜好来命名。
![体重秤_IS项目管理.png](./../../../images/weight_scale/体重秤_IS项目管理.png)
![体重秤_IS新建项目.png](./../../../images/weight_scale/体重秤_IS新建项目.png)
### 关联产品与设备
&emsp;&emsp;
为了使本项目能够获取到目标设备的信息,我们首先需要将该项目和我们在前一节创建的产品“体重秤”及设备“weight_scale”绑定。
&emsp;&emsp;
在项目控制台,点击左侧的“产品”,点击“关联物联网平台产品”。此时可以看见我们创建的“体重秤”,点击选中。
![体重秤_IS关联产品.png](./../../../images/weight_scale/体重秤_IS关联产品.png)
&emsp;&emsp;
在项目控制台,点击左侧的“设备”,点击“关联物联网平台设备”。此时可以看见我们创建的“weight_scale”,点击选中。
![体重秤_IS关联设备.png](./../../../images/weight_scale/体重秤_IS关联设备.png)
### 创建“移动应用”
&emsp;&emsp;
点击移动应用,选择新建输入应用名称“体重秤”点击确定
![体重秤_IS创建移动应用.png](./../../../images/weight_scale/体重秤_IS创建移动应用.png)
&emsp;&emsp;
点击创建完成的应用进入编辑页面,使用“空气质量优”模版创建页面
![体重秤_选择模版.png](./../../../images/weight_scale/体重秤_选择模版.png)
&emsp;&emsp;
编辑应用页面
![体重秤_页面编辑1.png](./../../../images/weight_scale/体重秤_页面编辑1.png)
![体重秤_页面编辑2.png](./../../../images/weight_scale/体重秤_页面编辑2.png)
![体重秤_页面编辑3.png](./../../../images/weight_scale/体重秤_页面编辑3.png)
![体重秤_页面编辑4.png](./../../../images/weight_scale/体重秤_页面编辑4.png)
&emsp;&emsp;
最终效果图
![体重秤_应用效果.png](./../../../images/weight_scale/体重秤_应用效果.png)
&emsp;&emsp;
效果预览
<div align="center">
<img src="./../../../images/weight_scale/体重秤_应用预览.png" width=50%/>
</div>
\ No newline at end of file
{
"name": "haasedu",
"version": "1.0.0",
"io": {
"hx711_clk": {
"type": "GPIO",
"port": 2,
"dir": "output",
"pull": "pullup"
},
"hx711_data": {
"type": "GPIO",
"port": 3,
"dir": "input",
"pull": "pullup"
},
"oled_spi": {
"type": "SPI",
"port": 1,
"mode": "master",
"freq": 26000000
},
"oled_dc": {
"type": "GPIO",
"port": 28,
"dir": "output",
"pull": "pullup"
},
"oled_res": {
"type": "GPIO",
"port": 30,
"dir": "output",
"pull": "pullup"
}
},
"debugLevel": "ERROR",
"repl": "disable"
}
\ No newline at end of file
from driver import GPIO
import utime
class Hx711(object):
def __init__(self, clkObj, dataObj):
self.clkObj = None
self.dataObj = None
if not isinstance(clkObj, GPIO):
raise ValueError("parameter is not an GPIO object")
if not isinstance(dataObj, GPIO):
raise ValueError("parameter is not an GPIO object")
self.clkObj = clkObj
self.dataObj = dataObj
def getValue(self):
if self.clkObj is None:
raise ValueError("invalid GPIO object")
if self.dataObj is None:
raise ValueError("invalid GPIO object")
count = 0
self.dataObj.write(1)
self.clkObj.write(0)
while(self.dataObj.read()):
utime.sleep_ms(1)
for i in range(24):
self.clkObj.write(1)
count = count<<1
self.clkObj.write(0)
if(self.dataObj.read()):
count += 1
self.clkObj.write(1)
count ^= 0x800000
self.clkObj.write(0)
return count
class EleScale(Hx711):
# capValue = 429.5是理论值,可通过调整该参数进行校准,
# 如果测量值偏大则适当增大capValue,如果测量值偏小则减小该值。
def __init__(self, clkObj, dataObj, capValue = 429.5):
Hx711.__init__(self, clkObj, dataObj)
self.noLoadOffset = self.__hx711Read(10)
self.capValue = capValue
def __hx711Read(self, times = 3):
# times必须 >= 3
cnt = 3 if (times <= 3) else times
idx = 0
data = [0] * cnt
while (idx < cnt):
data[idx] = self.getValue()
idx += 1
data.sort()
# 去掉最大最小值后的平均值作为结果返回
return round(sum(data[1:-1]) / (len(data) - 2))
def getWeight(self):
data = self.__hx711Read() - self.noLoadOffset
if (data <= 0):
weight = 0.0
else:
weight = data / self.capValue
return weight
# -*- encoding: utf-8 -*-
from driver import SPI
from driver import GPIO
from aliyunIoT import Device # iot组件是连接阿里云物联网平台的组件
import ujson # json字串解析库
import utime # 延时函数在utime库中
import ele_scale # 引入电子秤驱动库
import sh1106 # 引入hasseduk1 oled屏去掉
import netmgr as nm
# 电子秤对象
scaleObj = None
# OLED对象
oledObj = None
# 设备实例
clkDev = None
dataDev = None
dcDev = None
resDev = None
spi1Dev = None
# 三元组信息
productKey = "产品key"
deviceName = "设备名称"
deviceSecret = "设备密钥"
# Wi-Fi SSID和Password设置
wifi_ssid = "请填写您的路由器名称"
wifi_password = "请填写您的路由器密码"
# 物联网平台连接标志位
iot_connected = False
# 物联网设备实例
device = None
# 身高(cm)
g_height = 0.0
# 初始化设备
def scale_init():
global scaleObj
global clkDev, dataDev
clkDev = GPIO()
clkDev.open("hx711_clk")
dataDev = GPIO()
dataDev.open("hx711_data")
scaleObj = ele_scale.EleScale(clkDev, dataDev, 430.0)
#初始化自带oled屏幕模块
def oled_init():
global oledObj
global spi1Dev, dcDev, resDev
spi1Dev = SPI()
spi1Dev.open("oled_spi")
dcDev = GPIO()
dcDev.open("oled_dc")
resDev = GPIO()
resDev.open("oled_res")
oledObj = sh1106.SH1106_SPI(width=132, height=64, spi=spi1Dev, dc = dcDev, res = resDev)
oledObj.fill(0) #清屏背景黑色
oledObj.show()
# 关闭设备
def scale_deinit():
global clkDev, dataDev
clkDev.close()
dataDev.close()
def oled_deinit():
global spi1Dev, dcDev, resDev
dcDev.close()
spi1Dev.close()
resDev.close()
# 上传当前可供食用的宠物粮和累计投喂次数到物联网平台
def upload_msg(weight, bmi, strbmi, health_advice):
global device
data = ujson.dumps({
'weight': weight,
'bmi':bmi,
'strbmi':strbmi,
'health_advice':health_advice
})
# 生成上报到物联网平台的属性值字串
# 如下所示的属性标识符必须和物联网平台的属性一致
# "weight" - 代表体重
# "bmi" - 代表体重指数
# "strbmi" - 代表健康状态
# "health_advice" - 代表健康建议
uploadData = {'params': data}
# 上传数据到物联网平台
device.postProps(uploadData)
# 等待Wi-Fi成功连接到路由器
def get_wifi_status():
nm.init()
nm.disconnect()
# 连接到指定的路由器(路由器名称为wifi_ssid, 密码为:wifi_password)
nm.connect(wifi_ssid, wifi_password)
while True :
wifi_connected = nm.getStatus() # 获取Wi-Fi连接路由器的状态信息
if wifi_connected == 5: # nm.getStatus()返回5代表连线成功
break
else:
utime.sleep(0.5)
print("wifi_connected:", wifi_connected)
print("Wi-Fi connected")
print('DeviceIP:' + nm.getInfo()['ip']) # 打印Wi-Fi的IP地址信息
# 物联网平台连接成功的回调函数
def on_connect(data):
global iot_connected
iot_connected = True
# 设置props事件接收函数(当云平台向设备下发属性时)
def on_props(request):
global g_height
# {'height': xxx}
payload = ujson.loads(request['params'])
print("payload:%s"%payload)
# 获取dict状态字段 注意要验证键存在 否则会抛出异常
if "height" in payload.keys():
height = payload["height"]
if (height > 0):
g_height = height
print("height=%d\n"%g_height)
# 连接物联网平台
def connect_lk(productKey, deviceName, deviceSecret):
global device, iot_connected
key_info = {
'region' : 'cn-shanghai' , #实例的区域
'productKey': productKey , #物联网平台的PK
'deviceName': deviceName , #物联网平台的DeviceName
'deviceSecret': deviceSecret , #物联网平台的deviceSecret
'keepaliveSec': 60
}
# 将三元组信息设置到iot组件中
device = Device()
# 设定连接到物联网平台的回调函数,如果连接物联网平台成功,则调用on_connect
device.on(Device.ON_CONNECT, on_connect)
# 配置云端属性控制指令的回调函数,如果收到物联网平台发送的属性控制消息,则调用on_props
device.on(Device.ON_PROPS, on_props)
# 启动连接阿里云物联网平台过程
device.connect(key_info)
# 等待设备成功连接到物联网平台
while True:
if iot_connected:
print("物联网平台连接成功")
break
else:
print("sleep for 1 s")
utime.sleep(1)
print('sleep for 2s')
utime.sleep(2)
if __name__ == '__main__':
get_wifi_status()
connect_lk(productKey, deviceName, deviceSecret)
oled_init()
scale_init()
print("capValue=%.2f\n"%scaleObj.capValue)
while True:
weight = scaleObj.getWeight()
weight = weight / 1000
# 体重指数=体重(kg) / (身高(m)^2)
if (g_height > 0):
bmi = weight / ((g_height / 100)**2)
else:
bmi = 0.0
if (bmi > 0 and bmi <= 18.4):
strbmi = "偏轻"
health_advice = "少食多餐,保证供给充足的蛋白质和热量"
elif (bmi > 18.4 and bmi <= 23.9):
strbmi = "优秀"
health_advice = "饭后吃一些水果,保持完美身材"
elif (bmi > 23.9 and bmi <= 27.9):
strbmi = "偏重"
health_advice = "减少热量食物的摄入,建议多吃水果和蔬菜"
elif (bmi > 27.9):
strbmi = "肥胖"
health_advice = "严格控制热量摄入,并保持一定的运动量"
else:
strbmi = ""
health_advice = ""
print("weight: %.2f kg, height: %.1f cm, bmi: %.2f\n" %(weight, g_height, bmi))
oledObj.fill(0)
oledObj.text('weight: {:.2f} kg'.format(weight), 10, 20)
if (g_height > 0):
oledObj.text('height: {:.1f} cm'.format(g_height), 10, 5)
oledObj.text('bmi: {:.2f}'.format(bmi), 10, 35)
oledObj.show()
upload_msg(weight, bmi, strbmi, health_advice)
utime.sleep(2)
scale_deinit()
oled_deinit()
from micropython import const
import utime
import framebuf
from driver import SPI
from driver import GPIO
# register definitions
SET_SCAN_DIR = const(0xc0)
LOW_COLUMN_ADDRESS = const(0x00)
HIGH_COLUMN_ADDRESS = const(0x10)
SET_PAGE_ADDRESS = const(0xB0)
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xa4)
SET_NORM_INV = const(0xa6)
SET_DISP = const(0xae)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xa0)
SET_MUX_RATIO = const(0xa8)
SET_COM_OUT_DIR = const(0xc0)
SET_DISP_OFFSET = const(0xd3)
SET_COM_PIN_CFG = const(0xda)
SET_DISP_CLK_DIV = const(0xd5)
SET_PRECHARGE = const(0xd9)
SET_VCOM_DESEL = const(0xdb)
SET_CHARGE_PUMP = const(0x8d)
class SH1106:
def __init__(self, width, height):
self.width = width
self.height = height
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
fb = framebuf.FrameBuffer(
self.buffer, self.width, self.height, framebuf.MVLSB)
self.framebuf = fb
# set shortcuts for the methods of framebuf
self.fill = fb.fill
self.fillRect = fb.fill_rect
self.hline = fb.hline
self.vline = fb.vline
self.line = fb.line
self.rect = fb.rect
self.pixel = fb.pixel
self.scroll = fb.scroll
self.text = fb.text
self.blit = fb.blit
# print("init done")
self.initDisplay()
def initDisplay(self):
self.reset()
for cmd in (
SET_DISP | 0x00, # 关闭显示
SET_DISP_CLK_DIV, 0x80, # 设置时钟分频因子
SET_MUX_RATIO, self.height - 1, # 设置驱动路数 路数默认0x3F(1/64)
SET_DISP_OFFSET, 0x00, # 设置显示偏移 偏移默认为0
SET_DISP_START_LINE | 0x00, # 设置显示开始行[5:0]
SET_CHARGE_PUMP, 0x14, # 电荷泵设置 bit2,开启/关闭
# 设置内存地址模式 [1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
SET_MEM_ADDR, 0x02,
SET_SEG_REMAP | 0x01, # 段重定义设置,bit0:0,0->0;1,0->127;
# 设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
SET_COM_OUT_DIR | 0x08,
SET_COM_PIN_CFG, 0x12, # 设置COM硬件引脚配置 [5:4]配置
SET_PRECHARGE, 0xf1, # 设置预充电周期 [3:0],PHASE 1;[7:4],PHASE 2;
# 设置VCOMH 电压倍率 [6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
SET_VCOM_DESEL, 0x30,
SET_CONTRAST, 0xff, # 对比度设置 默认0x7F(范围1~255,越大越亮)
SET_ENTIRE_ON, # 全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
SET_NORM_INV, # 设置显示方式;bit0:1,反相显示;0,正常显示
SET_DISP | 0x01): # 开启显示
self.write_cmd(cmd)
self.fill(1)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
def rotate(self, flag, update=True):
if flag:
self.write_cmd(SET_SEG_REMAP | 0x01) # mirror display vertically
self.write_cmd(SET_SCAN_DIR | 0x08) # mirror display hor.
else:
self.write_cmd(SET_SEG_REMAP | 0x00)
self.write_cmd(SET_SCAN_DIR | 0x00)
if update:
self.show()
def sleep(self, value):
self.write_cmd(SET_DISP | (not value))
def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)
def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))
def show(self):
for page in range(self.height // 8):
self.write_cmd(SET_PAGE_ADDRESS | page)
self.write_cmd(LOW_COLUMN_ADDRESS)
self.write_cmd(HIGH_COLUMN_ADDRESS)
page_buffer = bytearray(self.width)
for i in range(self.width):
page_buffer[i] = self.buffer[self.width * page + i]
self.write_data(page_buffer)
def setBuffer(self, buffer):
for i in range(len(buffer)):
self.buffer[i] = buffer[i]
def drawXBM(self, x, y, w, h, bitmap):
x_byte = (w//8) + (w % 8 != 0)
for nbyte in range(len(bitmap)):
for bit in range(8):
if(bitmap[nbyte] & (0b10000000 >> bit)):
p_x = (nbyte % x_byte)*8+bit
p_y = nbyte//x_byte
self.pixel(x + p_x, y + p_y, 1)
# 以屏幕GRAM的原始制式去填充Buffer
def drawBuffer(self, x, y, w, h, bitmap):
y_byte = (h//8) + (h % 8 != 0)
for nbyte in range(len(bitmap)):
for bit in range(8):
if(bitmap[nbyte] & (1 << bit)):
p_y = (nbyte % y_byte)*8+bit
p_x = nbyte//y_byte
self.pixel(x + p_x, y + p_y, 1)
def fillRect(self, x, y, w, h, c):
self.fillRect(x, y, w, h, c)
def fillCircle(self, x0, y0, r, c):
x = 0
y = r
deltax = 3
deltay = 2 - r - r
d = 1 - r
#print(x)
#print(y)
#print(deltax)
#print(deltay)
#print(d)
self.pixel(x + x0, y + y0, c)
self.pixel(x + x0, -y + y0, c)
for i in range(-r + x0, r + x0):
self.pixel(i, y0, c)
while x < y:
if d < 0:
d += deltax
deltax += 2
x = x +1
else:
d += (deltax + deltay)
deltax += 2
deltay += 2
x = x +1
y = y -1
for i in range(-x + x0, x + x0):
self.pixel(i, -y + y0, c)
self.pixel(i, y + y0, c)
for i in range(-y + x0, y + x0):
self.pixel(i, -x + y0, c)
self.pixel(i, x + y0, c)
def drawCircle(self, x0, y0, r, w, c):
self.fillCircle(x0, y0, r, c)
self.fillCircle(x0, y0, r -w, 0)
def reset(self, res):
if res is not None:
res.write(1)
utime.sleep_ms(1)
res.write(0)
utime.sleep_ms(20)
res.write(1)
utime.sleep_ms(20)
class SH1106_I2C(SH1106):
def __init__(self, width, height, i2c, res=None, addr=0x3c):
self.i2c = i2c
self.addr = addr
self.res = res
self.temp = bytearray(2)
super().__init__(width, height)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.write(self.temp)
def write_data(self, buf):
send_buf = bytearray(1 + len(buf))
send_buf[0] = 0x40
for i in range(len(buf)):
send_buf[i+1] = buf[i]
print(send_buf)
self.i2c.write(send_buf)
def reset(self):
super().reset(self.res)
class SH1106_SPI(SH1106):
def __init__(self, width, height, spi, dc, res=None, cs=None):
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
super().__init__(width, height)
def write_cmd(self, cmd):
if self.cs is not None:
self.cs.write(1)
self.dc.write(0)
self.cs.write(0)
self.spi.write(bytearray([cmd]))
self.cs.write(1)
else:
self.dc.write(0)
self.spi.write(bytearray([cmd]))
def write_data(self, buf):
if self.cs is not None:
self.cs.write(1)
self.dc.write(1)
self.cs.write(0)
self.spi.write(buf)
self.cs.write(1)
else:
self.dc.write(1)
self.spi.write(buf)
def reset(self):
super().reset(self.res)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册