1.在PC上灌Python
2.準備一台Arduino
3.將Arduino接到PC USB port,但它們是透過UART COM port在通訊。
開始Arduino程式
1.在Adruino裡,寫程式,用來接受、辨識PC所傳來的字元。
在loop迴圈裡等待,Serial port的字元,假設是6個字以內。
void loop() {
delay(200);
while(Serial.available())
{
if (a<6)
{
inchar=Serial.read();
Strtest[a]=inchar;
a++;
Strtest[a]='\0';
serialdone=1;
}
}
2.接著將字元解讀出來, 假設收到的第0個字元是W,就代表I2C Write,
如果是R,就代表I2C Read。而第1,2個字元就代表register addres。第
3,4個字元代表data。如果第0個字元不是W也不是R,就代表不是I2C
操作,就會出現Wrong的訊息。但大家也可以定義其他的命令。
請參考3的函式說明,我們需要將接收到的1,2,3,4字元,由ASCII碼轉
成十六進制。用writeReg將address與data寫入I2C裝置。用readReg將
address寫入I2C裝置後,I2C裝置就會回覆value,再將這個value用
Serial.println(value,HEX);回傳給PC。PC的Python就可以顯示這個資
料了。
if (serialdone==1)
{
Serial.print(Strtest[0]);
Serial.print(Strtest[1]);
Serial.print(Strtest[2]);
Serial.print(Strtest[3]);
Serial.print(Strtest[4]);
int x,y,z;
y=int(Strtest[2]);
z=ASCtoHEX(y);
y=int(Strtest[1]);
z=ASCtoHEX(y)*16+z;
if (Strtest[0]== 'W')
{
y=int(Strtest[4]);
x=ASCtoHEX(y);
y=int(Strtest[3]);
x=ASCtoHEX(y)*16+x;
Serial.print("Write");
writeReg(z,x);
}
else if (Strtest[0]== 'R')
{
Serial.print("Read");
Serial.print(z,HEX);
Serial.print(readReg(z),HEX);
}
else
Serial.print("Wrong");
serialdone=0;
setcom=1;
a=0;
}
}
3.在loop迴圈以外,還定義了3個函式,用來做資料轉換。
ASCtoHEX:由於從PC接收到的字元,都是ASCII碼,所以用這個
函式來將它轉成16進制碼。
writeReg:要對I2C裝置寫入資料,需要address(reg)與data(valuein)
的數值。而i2cAddress是I2C裝置的Slave address,我是
設成固定的,不是從PC上輸入。
readReg:要對I2C裝置讀出資料,只需要填address(reg)的值,然
後I2C裝置就會回傳data(value),這就是那個reg裡的值。
int ASCtoDec(int asc)
{
if (asc>47 && asc <58)
asc=asc-48;
else if (asc>64 && asc<71)
asc=asc-55;
else if (asc>96 && asc<103)
asc=asc-87;
return asc;
}
void writeReg(int reg, word valuein){
Wire.beginTransmission(i2cAddress);
Wire.write(reg);
highbyte = valuein >>8;
lowbyte = valuein&0x00FF;
Wire.write(lowbyte); //send low byte first
Wire.write(highbyte);
Wire.endTransmission();
}
int readReg(int reg){
Wire.beginTransmission(i2cAddress);
Wire.write(reg);
Wire.endTransmission(false);
Wire.beginTransmission(i2cAddress);
Wire.requestFrom(i2cAddress, 2);
while(Wire.available()) // ensure all the data comes in
{
lowbyte=Wire.read();
highbyte=Wire.read();
}
value = highbyte * 256;
value = value + lowbyte;
Serial.println(value,HEX);
return value;
}
開始Python程式
1.建立COM port,這個"COM10"要是接上Arduino上的那個port。
請打開電腦的裝置管理員,確認Arduino是接到那個port,再去
改程式裡的"COM__"。
## Serial port setting.
ser =serial.Serial("COM10", timeout=2)
def SerialWrite(command):
ser.write(command)
rv=ser.readline()
#print (rv) # Read the newest output from the Arduino
print (rv.decode("utf-8"))
sleep(1) # Delay for one tenth of a second
ser.flushInput()
2.這是在GUI裡的I2C Write操作介面,用來送出字元給Arduino。
這段程式會送出W字元,還有送出address與data字元。
##===When button be pressed then Write I2C to device ============
def I2Cwrite():
print("Write I2C slaver address %s" % (e1.get()))
print("Write I2C register address %s" % (e2.get()))
print("Write I2C data %s" % (e3.get()))
reg_write="W"+e2.get()+e3.get()
cmd=reg_write.encode("utf-8")
##print(cmd)
SerialWrite(cmd)
2.這是在GUI裡的I2C Read操作介面,用來送出字元給Arduino。
這段程式會送出R字元還有address字元。
##===When button be pressed then Read I2C from device============
def I2Cread():
print("Read I2C slaver address %s" % (e1.get()))
print("Read I2C register address %s" % (e2.get()))
print("Read I2C data %s" % (e3.get()))
##print (rv.decode("utf-8"))
reg_read="R"+e2.get()
cmd=reg_read.encode("utf-8")
SerialWrite(cmd)
##ser.close()
2.這是用來建立Serial COM port連線,並顯示連線狀態。在連線過程
中,Aduino要回傳"Ready", PC的Python要接收到這個字元,表示
連線已經成功。
##==Serial connect and Get arduino Ready================
def Serial_Connect():
global Ready_flag
for i in range (1,10):
print("Checking...")
#Show to LabelA----------------
Str_index=""
str_check="th Checking...\n"
Str_index=str(i)
Label_msg="The " +Str_index +str_check
LabelA.config(fg='green',)
LabelA.config(text=Label_msg)
LabelA.update_idletasks()
## buttonStart.config(state="disabled")
master.update()
rv=ser.readline()
#Debug print (rv) # Read the newest output from the Arduino
print (rv.decode("utf-8"))
ser.flushInput()
sleep(0.5) # Delay
Str_Message=rv.decode("utf-8")
#Debug print(Str[0:5])
if Str_Message[0:5]=="Ready":
Ready_flag=1
print("Get Arduino Ready !")
#Show to LabelA----------------
LabelA.config(text="Get Arduino connecting Ready !")
LabelA.update_idletasks()
master.update()
break
elif i==9:
Ready_flag=0
LabelA.config(fg='red',)
LabelA.config(text="Can't connnect to Arduino successfully!")
## buttonStart.config(state="active")
LabelA.update_idletasks()
master.update()
sleep(1) # Delay
3.這段程式用來建立GUI介面,定義了各個Label與空白輸入格的位置。
## Windows setting
master = Tk()
master.title("Auduino control interface")
master.minsize(600,400)
#label.grid(row=0, column=0, columnspan=2, rowspan=2, padx=5, pady=5)
LabelA=Label(master,bg='white',fg='blue',text="Press 'Connect' Button to connect Arduino",width=60,height=4,)
LabelA.grid(row=0 ,columnspan=3)
Label(master, text="Slave address").grid(row=12)
Label(master, text="Data address").grid(row=16)
Label(master, text="Data").grid(row=18)
e1 = Entry(master)
e2 = Entry(master)
e3 = Entry(master)
e1.insert(5,"18")
e1.grid(row=12, column=1,columnspan=1)
e2.grid(row=16, column=1,columnspan=1)
e3.grid(row=18, column=1,columnspan=1)
Button(master,text="Connect",command=Serial_Connect).grid(row=3 ,column=0, sticky=W, pady=1)
Button(master, text='write', command=I2Cwrite).grid(row=22, column=2, sticky=W, pady=1)
Button(master, text='Read', command=I2Cread).grid(row=22, column=1 ,sticky=W, pady=1)