树莓派与Arduino通信

Arduino 开发板上的控制器芯片每秒可执行1600万条指令。

Arduino 使用基于C语言的Wiring库和基于Java的Processing库。
内存有2KB,闪存有32KB, and also 1kB of EEPROM for long-term storage.

使用 AVR-GCC 进行编译的。

In order to ensure the connection to Arduino, you need to have module cdc_acm loaded:

1
2
lsmod | grep acm # check, if not, use next command
sudo modprobe cdc_acm

Raspberry 联网的Arch Linux指令:

1
2
3
iptables -t nat -A POSTROUTING -o wlp2s0 -j MASQUERADE
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i enp3s0f1 -o wlp2s0 -j ACCEPT

If there is error with iptables saying ‘sudo modprobe ip_tables
sudo echo ‘ip_tables’ >> /etc/modules’. Then Open nat:

1
2
sudo modprobe ip_tables
sudo echo 'ip_tables' >> /etc/modules
1
2
3
iptables -I INPUT -p udp --dport 67 -i enp3s0f1 -j ACCEPT
iptables -I INPUT -p udp --dport 53 -s 192.168.137.0/24 -j ACCEPT
iptables -I INPUT -p tcp --dport 53 -s 192.168.137.0/24 -j ACCEPT

Experiment: One byte IIC transfer

Firstly ensure i2c interface is opened by raspberry pi.

1
sudo apt install build-essentials i2c-tools

then check by

1
sudo i2cdetect -y 1

If a problem happened showing ‘no i2c device found, /dev/i2c-1 or /dev/i2c/1’. You should edit /boot/config.txt, then open by uncomment

1
# dtparam=i2c1=on

Then install python2.7 package ‘smbus2’. You may install python-setuptools first. Then you can download source code to install or use pip install.

When connecting Arduino, check i2c pinout on your Pi by typing pinout. But this command might not be found on Raspbian Lite, so firstly you should install

1
2
sudo apt update
sudo apt install python-gpiozero

Python program on RPi

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
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import smbus
import time
bus = smbus.SMBus(1)
address = 0x20

def writeNumber(value):
bus.write_byte(address, value)
return -1

def readNumber():
number = bus.read_byte(address)
return number

while True:
var=input("Enter1–9:")
if not var:
continue
writeNumber(var)
print "RPI: Hi Arduino, I sent you ", var
# sleep one second
time.sleep(1)
number = readNumber()
print "Arduino: Hey RPI,I received a digit", number
print "======================================\n"

Arduino program:

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
#include <Wire.h>
#define IIC_SLAVE_ADDR 0x20
byte number = 0;

void loop() {
delay(100);
}

void sendData() {
Wire.write(number);
Serial.print("Data written: ");
Serial.println(number);
}

void receiveData(int byteCount) {
while(Wire.available()){
number = Wire.read();
Serial.print("data received: ");
Serial.println(number);
}
}

void setup() {
Serial.begin(9600); // for serial debugging
Wire.begin(IIC_SLAVE_ADDR);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
Serial.println("Ready");
}

Experiment: block of bytes I2C transfer

Python program on host

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import smbus
import time
bus = smbus.SMBus(1)
address = 0x20

def readString(len):
tmp = bus.read_i2c_block_data(address, 0, len)
message = "".join([chr(i) for i in tmp])
return message

while True:
var=input("Enter one byte to get a string:")
if not var:
continue

print "RPi: Hi Arduino, I sent you ", var
writeNumber(var)
# sleep one second
time.sleep(1)
message = readString(14)
print "RPi: I receive the string: ", message

Arduino program on guest transmitter:

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
#include <Wire.h>
#define IIC_SLAVE_ADDR 0x20
byte number = 0;
char message[14] = "short message";

void loop() {
delay(100);
}

void sendData() {
Wire.write(message);
Serial.print("Data written: ");
Serial.println(message);
}

void receiveData(int byteCount) {
while(Wire.available()){
number = Wire.read();
Serial.print("data received: ");
Serial.println(number);
}
}

void setup() {
Serial.begin(9600); // for serial debugging
Wire.begin(IIC_SLAVE_ADDR);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
Serial.println("Ready");
}

On Arduino you will see:

On RPi you will see:

This suggests that these two kinds of IIC protocals are slightly different. Because everytime when Pi requires Arduino to send a block of data, Arduino takes it as not only a send command but also an invalid receive command. Also Arduino won’t send the ‘\0’ of a string.
Therefore, we can let Arduino take the receive data 0 as a signal of bytes transfer.

Experiment: write random numbers into EEPROM of Arduino and read from Pi

Linux Troubleshooting Digital Signature

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×