一、介绍

树莓派综合项目2:智能小车(一)四轮驱动中,实现了代码输入对四个电机的简单控制,本章将使用Python 的图形开发界面的库——Tkinter 模块(Tk 接口),编写本地运行的图形界面,控制小车的前进后退、转向和原地转圈。

Tkinter是Python的标准GUI库,Python使用Tkinter可以快速的创建 GUI 应用程序。由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。

其它基础内容会在文集:树莓派基础实验当中讲解。

二、组件

★Raspberry Pi 3主板*1

★树莓派电源*1

★40P软排线*1

★L298N扩展板模块*1

★智能小车底板模块*1

★减速电机和车轮*4

★面包板*1

★跳线若干

三、实验原理

扩展板供电接法

(一)常见的图形开发界面的库

Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下:

Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。

wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。

PyQt:PyQt 是 Python 编程语言和 Qt 库的成功融合。Qt 本身是一个扩展的 C++ GUI 应用开发框架,Qt 可以在 UNIX、Windows 和 Mac OS X 上完美运行,因此 PyQt 是建立在 Qt 基础上的 Python 包装。所以 PyQt 也能跨平台使用。

(二)tk初始

注意:Python3.x 版本使用的库名为 tkinter,即首写字母 T 为小写。

import tkinter

创建一个GUI程序

1、导入 Tkinter 模块

2、创建控件

3、指定这个控件的 master, 即这个控件属于哪一个

4、告诉 GM(geometry manager) 有一个控件产生了。

实例(Python3.x):

#!/usr/bin/python3

import tkinter

top = tkinter.Tk()

# 进入消息循环

top.mainloop()

实例(Python2.x):

#!/usr/bin/python

# -*- coding: UTF-8 -*-

import Tkinter

top = Tkinter.Tk()

# 进入消息循环

top.mainloop()

以上代码执行结果如下图:

(三)创建基本窗口

#创建基本窗口

import tkinter as tk # 将tkinter导入到工程中

window = tk.Tk() # 创建窗体对象

window.title('musicplay') # 设置窗口标题

window.geometry('380x390') # 设置窗口大小,注意这里的x是英文字母x

#如果需要规定窗体打开的位置,可以在在380x390后面加上“+10+10”,

# 即横坐标为10,纵坐标为10 的位置

window.resizable(0,0) # 如果不想人为修改窗体的大小,可以加上这个

#window.iconbitmap('./logo.ico') # 设置窗体图标

#window.withdraw() # 隐藏窗口

#window.deiconify() # 显示窗口

window.mainloop() # 调用mainloop方法,使窗体一直执行下去

以上代码执行结果如下图:

那么在tkinter中又有哪些控件可以供我们使用呢?

tkinter控件表

本实验中只需要学会3种控件:标签控件来显示文字,按钮控件来控制方向,范围控件来控制油门。有点编程基础的同学几个小时就可以学会!

图形界面

(四)Label标签的使用

#设置标签的大小和字体

import tkinter as tk

window = tk.Tk()

window.title('Label的使用')

window.geometry('400x400')

label = tk.Label(window,text='我是一个标签', #text为显示的文本内容

bg='black',fg='white', #bg为背景色,fg为前景色

font=("华文行楷", 20), #设置字体为“华文行楷”,大小为20

width=20,height=3) #width为标签的宽,height为高

label.pack()

window.mainloop()

以上代码执行结果如下图:

label

#标签里插入图片,后面我们会用到按钮里插入图片

import tkinter as tk

window = tk.Tk()

window.title('Label的使用')

window.geometry('400x400')

photo = tk.PhotoImage(file='./up.png') #将图片加载到窗口中

#注意加载进来的图片只支持‘.gif’格式的图片,如果是其他格式的文件可以用其他工具转换一下,如PS、画图等

label2 = tk.Label(window,text='我是文字',

image=photo,

compound='center') #compound参数是指图片和文字之间的关系

label.pack()

'''

anchor可用的值:

left: 图像居左

right: 图像居右

top: 图像居上

bottom: 图像居下

center: 文字覆盖在图像上

'''

window.mainloop()

以上代码执行结果如下图:

label_grahic

(五)Button按键的使用

#创建一个按钮

#我们先创建一个宽20,长2,显示文字为‘单击’的按钮练练手

import tkinter as tk

window = tk.Tk()

window.title("button")

window.geometry("300x180")

tk.Button(window,width=20,height=2,text='单击').pack()

#如果后面我们需要对这个空间的属性进行修改,或者进行信息的获取,我们可以不指定对象,按键功能我们可以通过command参数实现

window.mainloop()

以上代码执行结果如下图:

button_1

#为按键添加一个回调函数

#现在我们已经将按钮创建出来了,那么当按钮按下去之后我们需要做些什么呢?这就需要设置command属性,添加回调函数了

import tkinter as tk

window = tk.Tk()

window.title("button")

window.geometry("300x180")

def danji(): #这个就是我们写的一个方法,下面由按钮进行调用

print('hello') #当按键按下时,打印‘hello’

tk.Button(window,width=20,height=2,text='单击',command=danji).pack()

#注意,在设置command属性的时候,回调函数是不加'()'的,我们一般调用方法是需要,但这里就是设置属性,不需要添加

window.mainloop()

以上代码执行结果如下图:

button_2

#在按键中放置图片

#有些时候我们需要将界面做的更漂亮一点,我们可以像label一样,用图片来美化我们的按钮

import tkinter as tk

window = tk.Tk()

photo = tk.PhotoImage(file='./up.png')

tk.Button(window, text='botton', compound='bottom', image=photo).pack()

tk.Button(window, text='top', compound='top', bitmap='error').pack()

#设置的相关属性和Label类似,故这里就不做赘述了

window.mainloop()

以上代码执行结果如下图:

button_3

(六)Scale滑动条的使用

#比如Windows下的音量控制,音乐或者视频的进度控制,

#都是用滑动条来实现的,本实验中用来控制油门

from tkinter import *

window = Tk()

Scale(window,label='accelerator', #设置显示的标签

from_=0,to=100, # 设置最大最小值

#注意设置最大值的属性不是'from',而是'from_',这是因为python中已经有了from关键字啦

resolution=1, # 设置步距值

orient=HORIZONTAL, # 设置水平方向

#如果我们想设置成垂直方向改怎么办呢?直接缺省这个属性就可以啦,默认就是垂直哒

).pack()

window.mainloop()

以上代码执行结果如下图:

scale_1

#绑定Scale的值为我们所用

from tkinter import *

window = Tk()

value = StringVar()

def s_print(text): #注意,Scale的回调函数需要给定形参,当触发时会将Scale的值传给函数

print(value.get())

print(text) #两者同样的效果

Scale(window,label='accelerator',

from_=0,to=100,

resolution=1,show=0,

variable=value,command=s_print

).pack()

window.mainloop()

以上代码执行结果如下图:

scale_2

(七)控件的定位

通过前面的文档我们已经知道Tkinter控件的简单使用,想要拥有一个简洁、合理的界面,控件布局就显得尤为重要了,而Tkinter提供了三种布局方式给我们。

1.pack是一种相对布局方式,指定控件的相对位置,精确位置会由系统完成。

pack布局没有任何属性参数,默认会自上而下垂直并且水平居中排列。我们可以通过side=TOP/BOTTOM/LEFT/RIGHT,控制控件的相对位置(上下左右),利用fill=x来是控件和窗体一样宽,用padx、pady、ipadx、ipady控制控件的边距。

from tkinter import *

window = Tk()

Label(window,text='first',bg='red').pack(fill=X,padx=10) #水平外边距

Label(window,text='second',bg='green').pack(fill=X,pady=10) #垂直外边距

Label(window,text='third',bg='yellow').pack(fill=X,ipadx=10) #水平内边距

Button(window,text='fourth',bg='blue').pack(fill=X,ipady=10) #垂直内边距

window.mainloop()

pack方式布局

2.grid布局我们可以理解成单元格布局方式,窗体就像是一个表格,横向、纵向划分了若干格子,我们将控件依次放入格子中进行定位。

from tkinter import *

window = Tk()

Label(window,text='first',bg='red').grid(row=1,column=1)

Label(window,text='second',bg='green').grid(row=1,column=3)

Label(window,text='third',bg='yellow').grid(row=2,column=2)

Button(window,text='fourth',bg='blue').grid(row=3,column=1)

window.mainloop()

grid布局方式

3.place布局是一种绝对位置布局方式,说的简单点就是坐标定位方式,窗体最左上角的位置就是原点(x=0,y=0)。本实验中我用的是这种方式。

from tkinter import *

window = Tk()

Label(window,text='first',bg='red').place(x=10,y=10)

Label(window,text='second',bg='green').place(x=10,y=40)

Label(window,text='third',bg='yellow').place(x=10,y=70)

Button(window,text='fourth',bg='blue').place(x=10,y=100)

window.mainloop()

place布局方式

四、实验步骤

树莓派(name)

树莓派(BOARD)

L298N小车扩展板

GPIO.0

11

ENA

GPIO.2

13

IN1

GPIO.3

15

IN2

GPIO.1

12

ENB

GPIO.4

16

IN3

GPIO.5

18

IN4

GND

GND

电池组供电负极

关于这里树莓派GND、L298N小车扩展板的电池组供电负极相连,是特殊情况下的情况,经测试发现:

如果树莓派用的是充电头供电,而L298N扩展板用的是电池组供电,这两个负极必须相连,否则马达不动。

如果树莓派用的是L298N扩展板接出来的5V供电,即两者同一个电源,则这里不用连接。

L298N小车扩展板

电池组

树莓派

电压表头

马达

电池+(-)

电池+(-)

5V供电

电源接口

+(-)

+(-)

T1(L后)

+(-)

T2(L前)

+(-)

T3(R前)

+(-)

T4(R后)

+(-)

刚开始时使用了面包板接线,GPIO使用的BCM模式,后来为了方便路面移动测试,让树莓派使用了多功能L298N智能小车扩展板上的5V供电,并且GPIO改用了BOARD模式。

智能小车四轮驱动电路图

扩展板供电接法1

第2步: 编写电机的驱动程序,文件名为motor_4w.py。与树莓派综合项目2:智能小车(一)四轮驱动中的程序完全相同。

该车的行进控制与履带车的行进控制类似:

前进和后退很简单,左右两边的方向都朝前或朝后,速度一致;

原地顺时针旋转时,左边轮子前进,右边轮子后退,速度一致;

原地逆时针旋转时,左边轮子后退,右边轮子前进,速度一致;

偏左前进时,左右两边的方向都朝前,左轮速度比右轮速度慢一点;

偏右前进时,左右两边的方向都朝前,左轮速度比右轮速度快一点;

偏左后退时,左右两边的方向都朝后,左轮速度比右轮速度慢一点;

偏右后退时,左右两边的方向都朝后,左轮速度比右轮速度快一点;

motor_4w.py:

#!/usr/bin/env python

import RPi.GPIO as GPIO

class SMPcar:

'''控制小车四轮动作的类'''

ENA = 11 #使能信号A,左边两轮

IN1 = 13 #信号输入1

IN2 = 15 #信号输入2

ENB = 12 #使能信号B,右边两轮

IN3 = 16 #信号输入3

IN4 = 18 #信号输入4

GPIO.setwarnings(False) #关闭警告

def setGPIO(self):

'''初始化引脚'''

GPIO.setmode(GPIO.BOARD)

GPIO.setup(SMPcar.ENA, GPIO.OUT)

GPIO.setup(SMPcar.IN1, GPIO.OUT)

GPIO.setup(SMPcar.IN2, GPIO.OUT)

GPIO.setup(SMPcar.ENB, GPIO.OUT)

GPIO.setup(SMPcar.IN3, GPIO.OUT)

GPIO.setup(SMPcar.IN4, GPIO.OUT)

def pwm(self,pwm):

'''初始化PWM(脉宽调制),返回PWM对象'''

EN_pwm = GPIO.PWM(pwm, 500)

EN_pwm.start(0)

return EN_pwm

def changespeed(self,pwm,speed):

'''通过脉宽调制改变占空比改变马达转速'''

pwm.ChangeDutyCycle(speed)

def clockwise(self,in1_pin,in2_pin):

'''马达顺时针转的信号

若电机旋转方向不正确,交换电机的正负极'''

GPIO.output(in1_pin, 1)

GPIO.output(in2_pin, 0)

def counter_clockwise(self,in1_pin,in2_pin):

'''马达逆时针转的信号'''

GPIO.output(in1_pin, 0)

GPIO.output(in2_pin, 1)

def stop_car(self,in1_pin,in2_pin):

'''马达制动的信号

使能信号为低电平,或者高电平(占空比设为100,

IN1和IN2都为0或1时)马达制动'''

GPIO.output(in1_pin, 0)

GPIO.output(in2_pin, 0)

def destroy(self,A,B):

'''结束程序时清空GPIO状态,

若不清空状态,再次运行时会有警告'''

A.stop()

B.stop()

GPIO.cleanup() # Release resource

if __name__ == '__main__': # Program start from here

try:

smpcar = SMPcar() #创建树莓派小车对象

smpcar.setGPIO() #初始化引脚

ENA_pwm=smpcar.pwm(smpcar.ENA) #初始化使能信号PWM,ENA为左边车轮

ENB_pwm=smpcar.pwm(smpcar.ENB) #初始化使能信号PWM,ENB为右边车轮

while True:

'''通过输入的命令改变马达转动

这里是考虑到后期,远程控制也是发送控制代码实现控制,

这里采用这种方式也很方便'''

cmd = input("Command, E.g. ff30ff30 :")

direction = cmd[0] #只输入字母b时,小车刹车

A_direction = cmd[0:2] #字符串0/1两位为控制A(左边车轮)方向信号

B_direction = cmd[4:6] #4/5位为控制B(右边车轮)方向信号

A_speed = cmd[2:4] #字符串2/3两位为控制A(左边车轮占空比)速度信号

B_speed = cmd[6:8] #字符串6/7两位为控制B(右边车轮占空比)速度信号

print (A_direction,B_direction,A_speed,B_speed) #测试用

if A_direction == "ff": #控制A(左边车轮)顺时针信号

smpcar.clockwise(smpcar.IN1,smpcar.IN2)

if A_direction == "00": #控制A(左边车轮)逆时针信号

smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)

if B_direction == "ff": #控制B(右边车轮)顺时针信号

smpcar.clockwise(smpcar.IN3,smpcar.IN4)

if B_direction == "00": #控制B(右边车轮)逆时针信号

smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)

if direction == "b": #小车刹车,IN1和IN2都为0,马达制动

smpcar.stop_car(smpcar.IN1,smpcar.IN2)

smpcar.stop_car(smpcar.IN3,smpcar.IN4)

continue #跳出本次循环

# 通过输入的两位数字设置占空比,改变马达转速

smpcar.changespeed(ENA_pwm,int(A_speed))

smpcar.changespeed(ENB_pwm,int(B_speed))

except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.

smpcar.destroy(ENA_pwm,ENB_pwm)

finally:

smpcar.destroy(ENA_pwm,ENB_pwm)

第3步: 编写图形控制界面,文件名为gui_motor_4w.py。界面控件一个个的添加和调试,每个控件的回调函数一个个调试,最终全部成功。先点击方向按钮,再滑动油门,小车行进;也可以先设定好油门,再点击方向按钮,小车行进。将这两个文件放进一个文件夹,只运行gui_motor_4w.py即可。

图形界面

上中和下中按钮为前进和后退,中左和中右为原地左转和原地右转,四个角上的按钮为向左、向右、向左后、向右后偏向行进,正中间的黑色暂停按钮为刹车和方向复位键。

gui_motor_4w.py:

from tkinter import * # 将tkinter导入到工程中

import motor_4w

'''acc_left为左边车轮油门的中间参数,

用于转向时,减低左轮的油门值,形成左右速差'''

acc_left = 0

acc_right = 0 #右边车轮油门的中间参数

smpcar = motor_4w.SMPcar()

smpcar.setGPIO() #初始化引脚

ENA_pwm=smpcar.pwm(smpcar.ENA) #初始化PWM(脉宽调制)

ENB_pwm=smpcar.pwm(smpcar.ENB)

root = Tk() # 创建窗体对象

root.wm_title('4w_motor Control') # 设置窗口标题

curWidth = 1050 #窗口宽度

curHight = 450 #窗口度

# 获取屏幕宽度和高度

scn_w, scn_h = root.maxsize()

#print(scn_w, scn_h)

# 计算中心坐标

cen_x = (scn_w - curWidth) / 2

cen_y = (scn_h - curHight) / 2

#print(cen_x, cen_y)

# 设置窗口初始大小和位置

size_xy = '%dx%d+%d+%d' % (curWidth, curHight, cen_x, cen_y) # 注意这里的x是英文字母x

root.geometry(size_xy) # 设置窗口大小

def leftTurn():

'''原地左转弯'''

acc_value = scale_accelerator.get() #获取油门值

smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2) #左边车轮后退

smpcar.clockwise(smpcar.IN3,smpcar.IN4) #右边车轮前进

smpcar.changespeed(ENA_pwm,(acc_value)) #根据刚获取的油门值调整速度

smpcar.changespeed(ENB_pwm,(acc_value))

def rightTurn():

'''原地右转弯'''

acc_value = scale_accelerator.get()

smpcar.clockwise(smpcar.IN1,smpcar.IN2)

smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,(acc_value))

smpcar.changespeed(ENB_pwm,(acc_value))

def forward():

'''直线前进'''

acc_value = scale_accelerator.get()

smpcar.clockwise(smpcar.IN1,smpcar.IN2)

smpcar.clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,(acc_value))

smpcar.changespeed(ENB_pwm,(acc_value))

def reverse():

'''直线后退'''

acc_value = scale_accelerator.get()

smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)

smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,(acc_value))

smpcar.changespeed(ENB_pwm,(acc_value))

def brake():

'''刹车'''

smpcar.stop_car(smpcar.IN1,smpcar.IN2)

smpcar.stop_car(smpcar.IN3,smpcar.IN4)

global acc_left

global acc_right

acc_left = 0 #左边车轮油门清零

acc_right = 0 #右边车轮油门清零

'''定义前进、后退、原地左转、原地右转、刹车插图的对象'''

up_im = PhotoImage(file='./up.png')

down_im = PhotoImage(file='./down.png')

left_im = PhotoImage(file='./left.png')

right_im = PhotoImage(file='./right.png')

brake_im = PhotoImage(file='./brake.png')

'''定义按钮'''

Button(root, text='forward',bd=10,image=up_im,command=forward).place(x=230,y=70) #定义前进按钮

Button(root, text='reverse',bd=10,image=down_im,command=reverse).place(x=230,y=330) #定义后退按钮

Button(root, text='left',bd=10,image=left_im,command=leftTurn).place(x=110,y=200) #定义原地左转按钮

Button(root, text='right',bd=10,image=right_im,command=rightTurn).place(x=350,y=200) #定义原地右转按钮

Button(root, text='brake',bd=10,image=brake_im,command=brake).place(x=230,y=200) #定义刹车按钮

a=0

'''a为中间参数,用于左前和左后按钮切换时,清零参数acc_left'''

def forward_left():

'''朝左前方转向行进'''

global a

global acc_left

if a == 0: #表明调用该函数前,已点击了 左后 按钮

acc_left = 0 #清零参数acc_left

a += 1 #点击 左前 按钮后,a会一定大于0

acc_value = scale_accelerator.get() #获取油门值

'''forward_left()函数被调用一次,参数acc_left累减5'''

acc_left -= 5

global acc_right

acc_right = 0 #左转时右轮参数acc_right清零

'''左轮的实际油门+参数acc_left得到左轮油门降低

而右轮不变的情况下,左轮慢,右轮快,车向左转向前进'''

acc_value_left = acc_value + acc_left

if acc_value_left < 0: #防止点左转次数过多

acc_value_left = 0

smpcar.clockwise(smpcar.IN1,smpcar.IN2) #车轮方向都向前行进

smpcar.clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,acc_value_left)

smpcar.changespeed(ENB_pwm,acc_value)

b=0

'''b为中间参数,用于右前和右后按钮切换时,清零参数acc_right'''

def forward_right():

'''朝右前方转向行进'''

global b

global acc_right

if b == 0: #表明调用该函数前,已点击了 右后 按钮

acc_right = 0 #清零参数acc_right

b += 1 #点击 右前 按钮时,b会一定大于0

acc_value = scale_accelerator.get() #获取油门值

'''forward_right()函数被调用一次,参数acc_right累减5'''

acc_right -= 5

global acc_left

acc_left = 0 #右转时左轮参数acc_left清零

'''右轮的实际油门+参数acc_right得到右轮油门降低

而左轮不变的情况下,左轮快,右轮慢,车向右转向前进'''

acc_value_right = acc_value + acc_right

if acc_value_right < 0:

acc_value_right = 0

smpcar.clockwise(smpcar.IN1,smpcar.IN2)

smpcar.clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,acc_value)

smpcar.changespeed(ENB_pwm,acc_value_right)

def reverse_left():

'''朝左后方转向倒车'''

global a

global acc_left

if a > 0: #表明调用该函数前,点击了 左前 按钮

acc_left = 0 #清零参数acc_left

a *= 0 #每点击 左后 按钮a就会置0

acc_value = scale_accelerator.get()

acc_left -= 5

global acc_right

acc_right = 0

acc_value_left = acc_value + acc_left

if acc_value_left < 0:

acc_value_left = 0

smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)

smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,acc_value_left)

smpcar.changespeed(ENB_pwm,acc_value)

def reverse_right():

'''朝右后方转向倒车'''

global b

global acc_right

if b > 0: #表明调用该函数前,点击了 右前 按钮

acc_right = 0 #清零参数acc_right

b *= 0 #每点击 右后 按钮b就会置0

acc_value = scale_accelerator.get()

acc_right -= 5

global acc_left

acc_left = 0

acc_value_right = acc_value + acc_right

if acc_value_right < 0:

acc_value_right = 0

smpcar.counter_clockwise(smpcar.IN1,smpcar.IN2)

smpcar.counter_clockwise(smpcar.IN3,smpcar.IN4)

smpcar.changespeed(ENA_pwm,acc_value)

smpcar.changespeed(ENB_pwm,acc_value_right)

'''定义左前、右前、左后、右后行进插图的对象'''

up_left_im = PhotoImage(file='./up_left.png')

up_right_im = PhotoImage(file='./up_right.png')

down_left_im = PhotoImage(file='./down_left.png')

down_right_im = PhotoImage(file='./down_right.png')

Button(root, text='up_left',bd=10,image=up_left_im,command=forward_left).place(x=110,y=70) #定义向前偏左行进按钮

Button(root, text='up_right',bd=10,image=up_right_im,command=forward_right).place(x=350,y=70) #定义向前偏右行进按钮

Button(root, text='down_left',bd=10,image=down_left_im,command=reverse_left).place(x=110,y=330) #定义向后偏左行进按钮

Button(root, text='down_right',bd=10,image=down_right_im,command=reverse_right).place(x=350,y=330) #定义向后偏右行进按钮

'''定义标签'''

label1 = Label(root,

text='Accelerator',

#bg='black',

fg='red',

font=("华文行楷", 20), #设置字体为“华文行楷”,大小为20

#width=9,height=3

)

label1.place(x=740,y=390)

'''根据scale滑动条的值,调整油门大小'''

def accelerator(v):

acc_value = int(v)

global acc_left

global acc_right

acc_value_left = acc_value + acc_left #加上中间参数

acc_value_right = acc_value + acc_right

if acc_value_left < 0:

acc_value_left = 0

if acc_value_right < 0:

acc_value_right = 0

smpcar.changespeed(ENA_pwm,acc_value_left)

smpcar.changespeed(ENB_pwm,acc_value_right)

'''定义scale滑动条'''

scale_accelerator = Scale(root,

#label='accelerator', # 设置显示的标签

from_=100, # 设置最大最小值

to=0,

resolution=2, # 设置步距值

orient=VERTICAL, #如果我们想设置成垂直方向改怎么办呢?直接缺省这个属性就可以啦,默认就是垂直

#show=0, # 隐藏滑动条的值

#variable=value_a, # 绑定Scale的值为我们所用

activebackground='red',

length=350,

width=30, # 设置Scale的宽度,默认是16。

sliderlength=50, # 滑块的大小。默认值是30

bd=10, # 设置Scale控件边框宽度

tickinterval=20, # 显示刻度,并定义刻度的粒度

troughcolor='red', # 设置滑动槽的背景颜色

command=accelerator

)

scale_accelerator.place(x=720,y=0)

root.mainloop()

smpcar.destroy(ENA_pwm,ENB_pwm) #退出程序时,清空GPIO状态

树莓派python交互界面实例_树莓派综合项目2:智能小车(二)tkinter图形界面控制...相关推荐

  1. 树莓派综合项目2:智能小车(二)tkinter图形界面控制

    一.介绍   阅读本篇文章前建议先参考前期文章:   树莓派基础实验34:L298N模块驱动直流电机实验   树莓派综合项目2:智能小车(一)四轮驱动   树莓派综合项目2:智能小车(一)四轮驱动中, ...

  2. python图形统计代码_python tkinter图形界面代码统计工具

    本文为大家分享了python tkinter图形界面代码统计工具,供大家参考,具体内容如下 #encoding=utf-8 import os,sys,time from collections im ...

  3. python图形界面代码_python tkinter图形界面代码统计工具(更新)

    本文为大家分享了python tkinter图形界面代码统计工具的更新版,供大家参考,具体内容如下 代码统计工具 修改了导出excel功能,把原来的主文件进行了拆分 code_count_window ...

  4. Java图形编程实验总结_实验二java图形界面编程2015级.doc

    实验二java图形界面编程2015级.doc 实验二JAVA图形界面编程一.实验目的熟悉JAVA运行环境,编程掌握JAVASWING组件的图形界面编程.二.实验环境微机,软件MYECLIPSE,JDK ...

  5. 树莓派python编程读取电压_《树莓派Python编程指南》——3.2 在结构体中存储值-阿里云开发者社区...

    本节书摘来自华章计算机<树莓派Python编程指南>一书中的第3章,第3.2节,作者:(美) Alex Bradbury Ben Everard更多章节内容可以访问云栖社区"华章 ...

  6. 树莓派4外置wifi天线_树莓派打造最强车载娱乐终端(1)音乐和WiFi

    开车跑长途的时候总觉得无聊,就会想起飞机上的娱乐终端,那么我们就来自己做一个吧! 这一系列文章里,我会按照功能划分,列出需要的软硬件,尽量做到互相独立,方便自由组合.今天我们先来实现最基本的音乐播放和 ...

  7. 树莓派python编程自学-一些缩短树莓派学习曲线的书籍、课程和网站

    树莓派是一款小型单板计算机,最初用于教学和学习编程和计算机科学.但如今它有更多用处.它是一种经济的低功耗计算机,人们将它用于各种各样的事情 -- 从家庭娱乐到服务器应用,再到物联网(IoT) 项目. ...

  8. 树莓派数据上传数据库_树莓派内部数据向domoticz的上传

    树莓派的数据上传->Domoticz 树莓派的温度检测到的数据可以通过API发送到domoticz 示例代码:#!/usr/bin/env python # -*- coding:utf-8 - ...

  9. 树莓派hdmi输出没声音_树莓派 4 开箱记

    树莓派 4 与其前代产品相比具有令人印象深刻的性能提升,而入门套件使其易于快速启动和运行. -- Anderson Silva(作者) 当树莓派 4 在 6 月底宣布发布 时,我没有迟疑,在发布的同一 ...

最新文章

  1. 【HDU - 3410 】 Passing the Message(单调栈)
  2. php将word转txt,PHP如何将将word文件转为pdf
  3. 微软为 Windows Terminal 推出全新 logo
  4. VC中连接mdb数据库及其数据读取方法
  5. 基础练习: 使用openssl命令创建RSA密钥
  6. Android官方教程翻译(2)——运行第一个程序
  7. 数据挖掘(Data Mining)扫盲笔记
  8. python刷b站视频浏览量_python刷B站播放量
  9. 产品读书《疯传:让你的产品、思想、行为像病毒一样入侵》
  10. 和一群程序猿的旧金山优胜美地之旅
  11. 适合中学生看的英文电影
  12. javascript技巧收集(200多个)
  13. SPI都不知道?还敢说懂Dubbo?面试官怼的我哑口无言啊!!!
  14. CentOS 7使用ttyd搭建一个WEB共享终端(WebSSH)
  15. 谁对云服务器安全负责:客户还是供应商 ?
  16. ae2020不支持的视频驱动程序_AE 2020版本安装提示系统兼容性报告怎么解决?
  17. Sencha Touch中 xclass和xtype区别
  18. matlab中累加的小程序,微信小程序学习用demo:数字累加,动态效果
  19. 云风Skynet——skynet非官方网站
  20. 【244】Python 说出下面list1,list2,list3的输出值(新的默认列表仅仅只在函数被定义时创建一次)...

热门文章

  1. Spring 中基于 AOP 的 XML操作方式
  2. CRM_ORDER_PR_ASSIGN_SELECT_CB
  3. SAP CRM WebClient UI data loss设计原理
  4. SAP UI5 web Component的React组件,如何实现事件响应
  5. 利用SAP Cloud Platform control center给global账号分配服务
  6. Angular Remove me测试应用的工作原理
  7. Cloud for Customer里的Shell menu manager
  8. include element into ABAP word document
  9. SAP Odata服务里filter的用法
  10. SAP S/4HANA生产订单状态含义