Tag Archives: python

Hello World

使用pandas+openpyxl生成多子表excel

虽然python+pandas自身有强大的数据分析和展现能力,可实际工作中,不是每个人都会coding的,所以,有时候把粗加工的数据,以excel的形式提供数据,会更灵活、更适合大部分,这里介绍一种可以生成多子表excel的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pandas as pd
from openpyxl import Workbook
from openpyxl.reader.excel import load_workbook
 
#数据暂存容器
xlsDatas = {}
#保存路径
savePath = '.../test-excel.xlsx'
#获取数据
df1 = pd.DataFrame(
    {
        '日期': ['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04'], 
        '订单数': [1234, 1321, 3456, 6543],
        '用户数': [234, 787, 987, 545]},
    columns=['日期', '订单数', '用户数']
)
xlsDatas['概况'] = df1  #子表名-子表数据
df2 = pd.DataFrame(
    [
        [56335, '兰州拉面', 15.0, '2021-01-01 12:12:12'], 
        [45135, '山西削面', 13.0, '2021-01-01 12:16:12'], 
        [16335, '兰州拉面', 15.0, '2021-01-01 12:32:12']
    ],
    index=list('123'),
    columns=['用户id', '产品名称', '消费金额', '消费日期']
)
xlsDatas['订单列表'] = df2
#使用Workbook保存数据
book0 = Workbook()
book0.save(savePath) #先保存一个空excel文件,然后往里塞子表,实际会有一个空的Sheet子表
book = load_workbook(savePath)
writer = pd.ExcelWriter(savePath, engine='openpyxl') #选择openpyxl引擎
writer.book = book
for k in xlsDatas :
    xlsDatas[k].to_excel(writer, sheet_name=k)
writer.save()

————
over
转载请注明出处:http://www.jiangkl.com/2021/08/pandas_openpyxl_excel

Hello World

python数字数组的join操作

从其他弱类型语言转到python,最大的感受就是,时不时会有这种感慨:
“卧槽,这样也行”
“卧槽,这也不行”
比如,数组的差值操作,可以直接这么取:
listDiff = list1 – list2
再比如,刚刚碰到的这个,数组的join操作
uIdArr是数字数组,要拼到sql里做查询
“,”.join(uIdArr)
这样?
会报错。。。很正常的一个操作,居然过不去。。。
需要吧userIdArr变成字符串数组
~~好吧
那么,开个for循环?
for当日可以,但是对于python这种追求简单的语言,必然有更简洁的方式:
“,”.join([str[uid] for uid in uIdArr])
——-
over

Hello World

apply与lambda简单搭配,一行代码实现按条件补齐数据

需求:订单列表里的点位信息,只有点位编号,没有点位场景类型,需要补齐这个数据,以便实现按场景分析订单数据

1
2
3
4
5
  orderDf = pd.read_csv('path...')  #订单数据
  nodePlaces = ... #查库,返回 点位编号 - 场景类型 字典数据
  orderDf['place'] = orderDf.apply(lambda x: nodePlaces[x.nodeId] if x.nodeId in nodePlaces else 0, axis = 1) //#补齐场景类型字段place
  print(orderDf.colums)  #查库补齐效果
  print(orderDf.tail(5))

实际测试,orderDf七千万行,nodePlaces五万个点位,添加place这一行,执行时间约为1分钟
over
—–
转载请注明出处:http://www.jiangkl.com/2021/07/pandas_apply_lambda
—–
两周后补充:
这个需求,还有一个效率更高的方法,就是使用pd.merge()
已上面的例子继续折腾:

1
2
3
4
5
6
  orderDf = pd.read_csv('path...')  #订单数据
  nodePlaces = ... #查库,返回 点位编号 - 场景类型 字典数据
  nodeDf = pd.DataFrame(list(nodePlaces()), columns=['nodeId', 'place']) #转成datafram
  orderDf = pd.merge(orderDf, nodeDf, on='nodeId', how='left') //#补齐场景类型字段place
  print(orderDf.colums)  #查库补齐效果
  print(orderDf.tail(5))

我没实际在使用上面的例子做测试,而是再另一个场景下使用了这种方法,实际对比,原来apply使用200秒的一个需求,换成这里的merge以后,降到了700毫秒,降了三个数量级!
不过这个方法也有个缺陷,那就是,如果nodePlaces里没有这个nodeId,orderDf的place字段,会被设置为NaN,解决的办法有两个:
1. 使用fillna替换
2. 构建nodeDf的时候,将nodePlaces里没有的nodeId也补进去

他山石

[转]python Pandas 常用方法备忘

关键缩写和包导入
缩写:

df:任意的Pandas DataFrame对象
s:任意的Pandas Series对象
导入包:

import pandas as pd
import numpy as np

导入数据
pd.read_csv(filename):从CSV文件导入数据
pd.read_table(filename):从限定分隔符的文本文件导入数据
pd.read_excel(filename):从Excel文件导入数据
pd.read_sql(query, connection_object):从SQL表/库导入数据
pd.read_json(json_string):从JSON格式的字符串导入数据
pd.read_html(url):解析URL、字符串或者HTML文件,抽取其中的tables表格
pd.read_clipboard():从你的粘贴板获取内容,并传给read_table()
pd.DataFrame(dict):从字典对象导入数据,Key是列名,Value是数据

导出数据
df.to_csv(filename):导出数据到CSV文件
df.to_excel(filename):导出数据到Excel文件
df.to_sql(table_name, connection_object):导出数据到SQL表
df.to_json(filename):以Json格式导出数据到文本文件

创建测试对象
pd.DataFrame(np.random.rand(20,5)):创建20行5列的随机数组成的DataFrame对象
pd.Series(my_list):从可迭代对象my_list创建一个Series对象
df.index = pd.date_range(‘1900/1/30’, periods=df.shape[0]):增加一个日期索引

查看、检查数据
df.head(n):查看DataFrame对象的前n行
df.tail(n):查看DataFrame对象的最后n行
df.shape():查看行数和列数
df.info():查看索引、数据类型和内存信息
df.describe():查看数值型列的汇总统计
s.value_counts(dropna=False):查看Series对象的唯一值和计数
df.apply(pd.Series.value_counts):查看DataFrame对象中每一列的唯一值和计数

数据选取
df[col]:根据列名,并以Series的形式返回列
df[[col1, col2]]:以DataFrame形式返回多列
s.iloc[0]:按位置选取数据
s.loc[‘index_one’]:按索引选取数据
df.iloc[0,:]:返回第一行
df.iloc[0,0]:返回第一列的第一个元素

数据清理
df.columns = [‘a’,’b’,’c’]:重命名列名
pd.isnull():检查DataFrame对象中的空值,并返回一个Boolean数组
pd.notnull():检查DataFrame对象中的非空值,并返回一个Boolean数组
df.dropna():删除所有包含空值的行
df.dropna(axis=1):删除所有包含空值的列
df.dropna(axis=1,thresh=n):删除所有小于n个非空值的行
df.duplicated():判断重复数据记录
df.drop_duplicates():删除数据记录,可指定特定列或全部
df.fillna(x):用x替换DataFrame对象中所有的空值
s.astype(float):将Series中的数据类型更改为float类型
s.replace(1,’one’):用‘one’代替所有等于1的值
s.replace([1,3],[‘one’,’three’]):用’one’代替1,用’three’代替3
df.rename(columns=lambda x: x + 1):批量更改列名
df.rename(columns={‘old_name’: ‘new_ name’}):选择性更改列名
df.set_index(‘column_one’):更改索引列
df.rename(index=lambda x: x + 1):批量重命名索引

数据处理:Filter、Sort和GroupBy
df[df[col] > 0.5]:选择col列的值大于0.5的行
df.sort_values(col1):按照列col1排序数据,默认升序排列
df.sort_values(col2, ascending=False):按照列col1降序排列数据
df.sort_values([col1,col2], ascending=[True,False]):先按列col1升序排列,后按col2降序排列数据
df.groupby(col):返回一个按列col进行分组的Groupby对象
df.groupby([col1,col2]):返回一个按多列进行分组的Groupby对象
df.groupby(col1)[col2]:返回按列col1进行分组后,列col2的均值
df.pivot_table(index=col1, values=[col2,col3], aggfunc=max):创建一个按列col1进行分组,并计算col2和col3的最大值的数据透视表
df.groupby(col1).agg(np.mean):返回按列col1分组的所有列的均值
data.apply(np.mean):对DataFrame中的每一列应用函数np.mean
data.apply(np.max,axis=1):对DataFrame中的每一行应用函数np.max

数据合并
df1.append(df2):将df2中的行添加到df1的尾部
df.concat([df1, df2],axis=1):将df2中的列添加到df1的尾部
df1.join(df2,on=col1,how=’inner’):对df1的列和df2的列执行SQL形式的join

数据统计
df.describe():查看数据值列的汇总统计
df.mean():返回所有列的均值
df.corr():返回列与列之间的相关系数
df.count():返回每一列中的非空值的个数
df.max():返回每一列的最大值
df.min():返回每一列的最小值
df.median():返回每一列的中位数
df.std():返回每一列的标准差

转自:https://www.cnblogs.com/feiqixia/p/11241925.html

Hello World

python读取csv/json/xml

python(3.x)读取csv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import csv
 
filename = 'xxx.csv'
fi = [] 
ls = []
 
with open(filename, 'r', encoding='gbk') as csvfile:
    reader = csv.reader(csvfile)
    fi = next(reader)
    for lr in reader:
        ls.append(lr)
 
for lr in ls[:5]:
    print(lr)

当然,使用专业类库,会更简单:

1
2
3
4
5
6
7
import pandas as pd
 
filename = 'xxx.csv'
 
data = pd.read_csv(filename, encoding='gbk')
 
print(data.head(5))

读取json:

1
2
3
4
5
6
7
8
import json
 
filename = 'xxx.json'
 
with open(filename) as f:
    jsondata = json.load(f)
 
print(jsondata)

当然,pandas里也有更高效的读取json的read_json(),不过用它读取多维不定格式的json时,会报错“ValueError: arrays must all be same length”,这里就不再演示了

读取xml,并转变为json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import json
import xml.etree.ElementTree as ET
import xmltodict
 
filename = 'xxx/s1.xml'
 
tree = ET.parse(filename)
xmldata = tree.getroot()
 
xmlstr = ET.tostring(xmldata, encoding='utf8', method='xml')
xmldict = xmltodict.parse(xmlstr, encoding='utf8')
 
datadict = dict(xmldict)
 
print(datadict)
 
filename2 = 'xxxx/s1.json'
with open(filename2, 'w+') as jsonfile:
    json.dump(datadict, jsonfile, indent=4, sort_keys=True)

注:
1. xmltodict可能需要安装:pip install xmltodict
2. xmltodict.parse对xml格式要求较严格,如果某节点字符串开头第一个字符是数值,createElement时可能会报错

Hello World

[转]python参考–字符串方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
capitalize()  #把字符串的第一个字符改为大写
casefold()    #把整个字符串的所有字符改为小写
center(width) #将字符串居中,并使用空格填充至长度 width 的新字符串
count(sub[, start[, end]]) #返回 sub 在字符串里边出现的次数,start 和 end 参数表示范围,可选。
encode(encoding='utf-8', errors='strict') #以 encoding 指定的编码格式对字符串进行编码。
endswith(sub[, start[, end]])  #检查字符串是否以 sub 子字符串结束,如果是返回 True,否则返回 False。start 和 end 参数表示范围,可选。
expandtabs([tabsize=8])  #把字符串中的 tab 符号(\t)转换为空格,如不指定参数,默认的空格数是 tabsize=8。
find(sub[, start[, end]])  #检测 sub 是否包含在字符串中,如果有则返回索引值,否则返回 -1,start 和 end 参数表示范围,可选。
index(sub[, start[, end]])  #跟 find 方法一样,不过如果 sub 不在 string 中会产生一个异常。
isalnum()  #如果字符串至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False。
isalpha()  #如果字符串至少有一个字符并且所有字符都是字母则返回 True,否则返回 False。
isdecimal()  #如果字符串只包含十进制数字则返回 True,否则返回 False。
isdigit()  #如果字符串只包含数字则返回 True,否则返回 False。
islower()  #如果字符串中至少包含一个区分大小写的字符,并且这些字符都是小写,则返回 True,否则返回 False。
isnumeric()  #如果字符串中只包含数字字符,则返回 True,否则返回 False。
isspace()  #如果字符串中只包含空格,则返回 True,否则返回 False。
istitle()  #如果字符串是标题化(所有的单词都是以大写开始,其余字母均小写),则返回 True,否则返回 False。
isupper()  #如果字符串中至少包含一个区分大小写的字符,并且这些字符都是大写,则返回 True,否则返回 False。
join(sub)  #以字符串作为分隔符,插入到 sub 中所有的字符之间。
ljust(width)  #返回一个左对齐的字符串,并使用空格填充至长度为 width 的新字符串。
lower()  #转换字符串中所有大写字符为小写。
lstrip()  #去掉字符串左边的所有空格
partition(sub)  #找到子字符串 sub,把字符串分成一个 3 元组 (pre_sub, sub, fol_sub),如果字符串中不包含 sub 则返回 ('原字符串', '', '')
replace(old, new[, count])  #把字符串中的 old 子字符串替换成 new 子字符串,如果 count 指定,则替换不超过 count 次。
rfind(sub[, start[, end]])  #类似于 find() 方法,不过是从右边开始查找。
rindex(sub[, start[, end]])  #类似于 index() 方法,不过是从右边开始。
rjust(width)  #返回一个右对齐的字符串,并使用空格填充至长度为 width 的新字符串。
rpartition(sub)  #类似于 partition() 方法,不过是从右边开始查找。
rstrip()  #删除字符串末尾的空格。
split(sep=None, maxsplit=-1)  #不带参数默认是以空格为分隔符切片字符串,如果 maxsplit 参数有设置,则仅分隔 maxsplit 个子字符串,返回切片后的子字符串拼接的列表。
splitlines(([keepends]))  #按照 '\n' 分隔,返回一个包含各行作为元素的列表,如果 keepends 参数指定,则返回前 keepends 行。
startswith(prefix[, start[, end]])  #检查字符串是否以 prefix 开头,是则返回 True,否则返回 False。start 和 end 参数可以指定范围检查,可选。
strip([chars])  #删除字符串前边和后边所有的空格,chars 参数可以定制删除的字符,可选。
swapcase()  #翻转字符串中的大小写。
title()  #返回标题化(所有的单词都是以大写开始,其余字母均小写)的字符串。
translate(table)  #根据 table 的规则(可以由 str.maketrans('a', 'b') 定制)转换字符串中的字符。
upper()  #转换字符串中的所有小写字符为大写。
zfill(width)  #返回长度为 width 的字符串,原字符串右对齐,前边用 0 填充。
format('s1', 's2', ...) #以此,以s1/s2代替目标字符串中的“{0},{1}”; “{a} have a {b}.”.format(a="I", b="pen")

转自:http://bbs.fishc.com/thread-38992-1-1.html

Hello World

python如何连接mysql

python3.x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import pymysql
 
#简单封装的query方法
def query(sql):
    conn = pymysql.connect(host = 'xx.xx', port=3306, user = 'xx', passwd = "xx", db='xx')
    cur  = conn.cursor()
    cur.execute(sql)
    r    = []
    for row in cur:
        r.append(row)
    cur.close()
    conn.close()
    return r
 
sql  = "select count(id) from tabName"
rd   = query(sql)
print(rd[0])

ok,就是这样
—————–
btw,好久没写新东西,主要是最近一年做的,新东西不多,大部分需要代码实现的东西,都是统计类类的需求。利用手头的这点货,php、nodejs,实现简单的统计分析,有时真的很吃力,效率也低。所以,新的一年,以统计为出口,开一个新技能树:python。这里从最简单的mysql连接开始~~~

Hello World 软硬兼施

树莓派控制直流电机

使用树莓派控制直流电机,包括控制转速和转向,这里使用的是L293D驱动芯片,简单易用
芯片接线方式如下图所示

L293D可以控制两路直流电机,这里做个简单演示,只控制一路,所以只用到了一侧的管脚
需要树莓派的三个gpio口,分别连L293D的1、2、7
1是使能信号,写死成高电平就行了
2是pwm,“脉冲宽度调制”,也就是宽边宽度的方波,7需要的信号与2相同
2、7的区别是,2或7有pwm信号是,电机转向是相反的
呵呵,偷个懒,继续简化,这里在用到2,将接2的线头改插到7上,电机如果翻转,也就成功了
也就是说,实际演示树莓派只用了2个gpio口~~嘻嘻

然后再看怎么用树莓派产生pwm信号~很简单:

1
2
3
4
5
6
GPIO.setup(gpiox, GPIO.OUT)
p = GPIO.PWM(gpiox, frequency) #创建一个 PWM 实例:
p.start(dc)   # dc 代表占空比(范围:0.0 <= dc >= 100.0)
p.ChangeFrequency(freq)   # freq 为设置的新频率,单位为 Hz
p.ChangeDutyCycle(dc)  # 修改占空比,范围:0.0 <= dc >= 100.0
p.stop() 停止 PWM:

好了,下面是整体的测试代码~~~其实是在一个“呼吸灯”的基础上加了一个使能信号,对应的,看到的是电机加速-减速-加速的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#coding:utf-8 脉宽调制(PWM)输出
import time
import RPi.GPIO as GPIO
 
def init(pwm, en):
    GPIO.setmode(GPIO.BCM)
    #使能信号
    GPIO.setup(en, GPIO.OUT)
    GPIO.output(en, True)
    GPIO.setup(pwm, GPIO.OUT)
    p = GPIO.PWM(pwm, 50)
    p.start(0)
    try:
        while 1: #周期性修改占空比
            for dc in range(0, 101, 5):
                p.ChangeDutyCycle(dc);
                time.sleep(0.1)
            for dc in range(100, -1, -5):
                p.ChangeDutyCycle(dc);
                time.sleep(0.1)
    except KeyboardInterrupt:
        pass
    p.stop()
    GPIO.cleanup()
 
if __name__ == '__main__':
    init(20, 16)  # gpio20接L293D的2或7管脚,gpio16接1管脚

接线图如下(有点乱,电机的电源是一块12v的电池,没有出现在画面中,另外,呼吸灯还保留着)
另外,电机两极最好并联一个陶瓷电容,转动会更平滑:


————–over
———————-后记
如何用树莓派控制电机,进而控制小车的前进、后退、转向,这个问题困扰了我半个多月
大学四年,唯一值得炫耀的,是大三暑假时参加的电子设计大赛集训,后来还拿了一等奖,也是在那次的比赛作品中,接触到了可变频宽方波控制功率输出的思路,貌似现在满街跑的电动车也是这么控制车速的
这样,树莓派产生这种方波就行了,当时还不知道树莓派有专门的pmw输出,想的还是程序写循环、通过不同的sleep长度、输出方波。。。
然后下一个问题,方波信号是3.3v,怎么控制12v的电机?
开始的想法是继电器,但是继电器这东西,连变频方波,肯定不连续,估计效果会很差
两一个思路是三极管、场效应管放大,拿手头的三极管搭了一个两级的放大电路,不成功,而且第二级管子发热特别厉害~~这个思路肯定是通的,L293D内部也就是这玩意,只是咱水平不够
于是继续搜索解决方案,然后在“极客范”找到了类似功能的文章,不过它讲的貌似是老版的树莓派,产生pmw信号的方法很麻烦;然后最后找到一篇树莓派pmw信号实现呼吸灯的介绍,于是二者结合,有了上面的方案
~~呵呵,作为已有近10年没怎么搞过硬件的人,能搞得这个程度,自己还算满意 🙂

Hello World 软硬兼施

使用树莓派驱动超声测距模块

这里用的模块,是SRF04超声测距模块,淘宝上买的,10块钱,加八块运费

测距的时序图如下:

想给触发信号trig一个约10us的高电平,模块会发送测距信号,回响信号echo会输出一个高电平,高电平的次序时间,与检测距离成正比,这就是该模块超声定位的基本原理
先面是相关的pytho代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#srf04.py coding:utf-8 srf04超声测距模块驱动
import RPi.GPIO as GPIO
import time
from time import ctime, sleep
 
__gproTrig = 16    trig
__gproEcho = 12    echo
#初始化输入、输出gpio口
def init():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(__gproTrig, GPIO.OUT)
    GPIO.setup(__gproEcho, GPIO.IN)
 
def measure():
    #确保启动前为低电平
    GPIO.output(__gproTrig, False)
    time.sleep(0.0001)
    #启动测距
    GPIO.output(__gproTrig, True)
    time.sleep(0.00001) #10us
    GPIO.output(__gproTrig, False)
    #开始记时
    start   = 0
    stop    = 0
   #         print("measure--1")
    while start == 0 or stop == 0:
        val     = GPIO.input(__gproEcho)
        if stop == 0 and start == 0 and val == 1:
   #         print("measure--2")
            start = time.time()
        if start > 0 and stop == 0 and val == 0:
      #      print("measure--3")
            stop = time.time()
    #根据驱动公式计算测距结果
    elapsed = stop - start
    distance = (elapsed * 34300)/2
    return distance
 
if __name__ == '__main__':
    init()
    for i in range(300)://五分钟测试
     #   print("srf05-start:", i)
        dis = measure()
        print('--------------dis:', dis)
        sleep(1)

over~
~~~~~~后记
其实这个超声模块已经到手很久了,但是看到驱动要使用10us信号后,就一直纠结怎么来做10us的时钟,测试用python的sleep实现时钟,又特别不精确,那么,就需要100MHz的晶振,可晶振怎么接到树莓派上。。。于是就卡到这里了。
后来偶然搜到了类似模块的驱动方式,才发现其实是我想多了,要什么晶振,sleep足够了~~~嘿嘿,照着这种思路做下去,居然真的成功了
很多事情就是这样:先有一个大概的思路,没有更好地办法的情况下,就先照着这个思路走,大部分时候都能走的过去

——本文为原创,转载请注明出处 昆仑的山头

Hello World 软硬兼施

树莓派GPIO使用练习–点亮LED点阵

这里只是为了练习GPIO的使用,没有加任何的译码设备,也没加任何的放大设备,直接用树莓派的16个gpio引脚,连接一个8*8LED点阵的16个引脚,考虑到树莓派所能提供的电流不能太大,所以统一在点阵的8个阳极各加了一个1kΩ的电阻

8*8电阻的16个引脚,8个阳极,8个阴极,我们可以第一为R1~R8、C1~C8(考虑到点阵是方形的,所以不去区分行列,只区分阴阳,上面的R/C和“阴/阳”的对应关系,请根据实际共阴还是共阳区分清楚)

当我们给R1/C1两个管脚上电时(即在树莓派中,将R1对应的GPIO口拉到高电平,C1拉到低电平),第一行、第一列的这个点就会亮起来,同理,给R3/C5上电,[3, 5]的这个点会连起来

于是,我们可以通过这种方式依次点亮所有的点
。。。

于是,问题来了

如果我想同时点亮[3, 5]/[3, 6]/[4, 6]三个点,就需要同时拉高C3/C4,拉低R5/R6,可是,如果我做了这个操作,[4, 5]这个点也会亮起。。。这怎么办哪?

答案时,依次先点亮[3, 5]/[3, 6],熄灭这两个点,再点亮[4, 6],。。。熄灭[4, 6],点亮[3, 5]/[3, 6],如此往复,当这种切换的频率足够高时,由于认得视觉暂留,看到这三个点就是同时亮起的,也就是说,同一时刻,自会有单独一行、或者一列有点在发光

呵呵,很熟悉吧,电影、大屁股显示器什么的,和这个原理类似

好的,明白了原理,就可以动手写程序吧

这里使用树莓派最主流的编程语言:python,显示的东西,是“Hello word”,左右移动显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import RPi.GPIO as GPIO  #导入必要的python库
import time
 
#Hello World 字模
vhws = [
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0],
]
 
#左移还是右移
isRig = 1
vhwi = 0
#此函数返回当前时间点当前帧需要显示的8*8数组
def hwv():
  global isRig
  global vhwi
  l = len(vhws[0])
  if isRig &gt; 0:
    vhwi += 1
  else:
    vhwi -= 1
  if vhwi &gt;= (l - 8):
    isRig = 0
  if vhwi  0):
    if timeLine % 10 == 0:
      nowV = hwv()
    #双层循环实现的扫描显示  
    for i in range(0, len(nowV)):
      allOver()
      #拉低所有阴极
      GPIO.output(rs[i], GPIO.LOW)
      for j in range(0, len(nowV[i])):
        if nowV[i][j] &gt; 0:
          GPIO.output(cs[j], GPIO.HIGH) #点亮这个点
        else:
          GPIO.output(cs[j], GPIO.LOW)  #不点亮
        time.sleep(sleepTime)
    timeLine = timeLine - 1
  return
#ledtest 17 27 22 5 6 13 19 26 18 23 24 25 12 16 20 21
#这里是管脚对应关系
rs = [21, 20, 16, 12, 25, 24, 23, 18] #R1:13 R2:3 R3:4 R4:10 R5:6 R6:11 R7:15 R8:16
cs = [26, 19, 13, 6, 5, 22, 27, 17] #C1:5 C2:2 C3:7 C4:1 C5:12 C6:8 C7:14 C8:9
#开始
def startVs():
  GPIO.setmode(GPIO.BCM)
  for i in xrange(8):
    GPIO.setup(cs[i], GPIO.OUT)
    GPIO.setup(rs[i], GPIO.OUT)
  allOver()
  return
#关闭
def stopVs():
  GPIO.cleanup()
  return
#将所有管脚置为反响,即熄灭所有
def allOver():
  for i in xrange(8):
    GPIO.output(cs[i], GPIO.LOW)
    GPIO.output(rs[i], GPIO.HIGH)
  return
 
#timeLine = 1000
frames = 60
#显示一个8*8数组
def viewArr():
  timeLine = 1000
  sleepTime = 0.0001 #1 / (frames * 8)
  while(timeLine > 0):
    if timeLine % 10 == 0:
      nowV = hwv()
    for i in range(0, len(nowV)):
      allOver()#每次点亮前,先熄灭所有
      GPIO.output(rs[i], GPIO.LOW)
      for j in range(0, len(nowV[i])):
        if nowV[i][j] &gt; 0:
          GPIO.output(cs[j], GPIO.HIGH)  #点亮
        else:
          GPIO.output(cs[j], GPIO.LOW)   #不点亮
        time.sleep(sleepTime)  #扫屏的时延
  timeLine = timeLine - 1   #显示时常控制
return
 
if __name__ == '__main__':
  startVs()
  viewArr()
  stopVs()

下面是实际效果的几个截图:

下面两个是线路连接:

转载请注明出处:昆仑的山头