Linkit 系列博文:
联发科Linkit 7688 (一) 上手及在Mac下搭建OpenWrt交叉编译环境,C语言编译Hello,World
联发科Linkit 7688 (二)GPIO基本操作与C语言编程
联发科Linkit 7688 DUO(三): 通过 Arduino 控制外设和传感器
Linkit 7688 DUO(四): 接上各种Arduino传感器和模块——基础篇
Linkit 7688 DUO(五) 接上各种Arduino传感器和模块—扩展篇
Linkit 7688 DUO(六) 加入MQTT物联网协议
前一篇讲了 Linkit 7688DUO开发板接上一些典型Arduino传感器的作法。
本篇,我们要为开发板接上更多的Arduino的传感器和模块了。
一、 前篇概要:
Linkit 7688 DUO开发板上有两个处理器芯片。
一片是 Linkit 7688, 主处理器
一片是 ATmega32U4, 这是Arduino的处理芯片,提供Arduino编程接口,用于控制传感器外设等
两个处理器通过内部串口相连。
Linkit 7688 DUO开发板上, 从ATmega32U4管脚接出的众多管脚,其中:D0-D13 为数字IO口, A0-A5为模拟IO口, S0-S3为串口设备SPI管脚
前篇,我们练习了在开发板上接入LED、开关、继电器、蜂鸣器等, 并制定了一个两个处理器串口通讯的消息协议。
在开发中, 要写两个程序:
1, 写一个Arduino程序, 写入ATmega32U4中。Arduino程序通过串口接收主处理器Linkit 7688送来的消息, 执行相应动作。
2, 写一个主程序,写入Linkit7688中。 主程序通过串口向 ATmega32U4 发送消息
二、温度湿度传感器 (Temperature & Humidity Sensor), 见下图
编一个Arduino程序如下:采用消息协议,当收到消息,则测量温度、湿度,并发送结果消息到主控板。
注意:程序要用到 dht库(请确保已装好)。
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#include <dht.h>
#define COMMAND_TEMPERATURE 't'
#define ACK_TEMPERATURE 'u'
dht DHT; // dht object
int pinDHT = 3; //pin connects to DHT Temperature/Humidity sensor
void setup() {
MessageInit(57600); //init message
pinMode(pinDHT, INPUT); //set pinDHT INPUT
}
void getTemperature() {
//Serial.println("in");
int ret = DHT.read11(pinDHT);
switch (ret)
{
case 0: // ok
{
unsigned char buf[3];
buf[0] = (int)DHT.temperature; //integer part of temperature
buf[1] = (int)((DHT.temperature - (int)DHT.temperature)*10); //one digit frac
buf[2] = (int)DHT.humidity; //integer part of humidity
MessageSend( ACK_TEMPERATURE, buf, 3 ); //send ACK_TEMPERATURE message back
return;
}
case -1: break; //checksum error
case -2: break; //Time out error
default: break; //unknown error
}
MessageNAK( COMMAND_TEMPERATURE ); //send NAK message back
}
void loop() {
if ( MessageReceive() ) {
if ( MessageCommand() == COMMAND_TEMPERATURE ) {
getTemperature();
}
}
}
Arduino程序等待 COMMAND_TEMPERATURE消息, 调用getTemperature()函数 ,该函数中调用 DHT.read11()读取传感器数据。如果读取数据成功,返回 ACK_TEMPERATURE消息,消息内容三个字节,第一个字节是温度的整数位、第二个字节是温度的小数第1位。第三字节是湿度.
编一个C语言主程序 temperature_test.c,采用消息协议,向Arduino发送COMMAND_TEMPERATURE消息送到,等待Arduino返回 ACK_TEMPERATURE消息, 读取其中的温度和湿度值打印出来。
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_TEMPERATURE 't'
#define ACK_TEMPERATURE 'u'
//wait ACK_TEMPERATURE message from Arduino
int wait_ack_message(message_t * msg) {
int times, ret;
times = 0;
while ( (ret = message_receive(msg)) != 1 && times++ < 30) {
usleep(30*1000);
}
if ( ret == 1 ) {
if ( message_command(msg) == ACK_TEMPERATURE ) {
char temperature = (char)message_data(msg, 0);
printf("Temperature: %d.%d, Humidity:%d\n", temperature,
message_data(msg, 1), message_data(msg, 2));
fflush(stdout);
return 1;
}
}
return 0;
}
int main(int argc, char **argv) {
int fd; //file descriptor of serial port
message_t msg; //message object
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
message_send( &msg, COMMAND_TEMPERATURE, NULL, 0); //send COMMAND_TEMPERATURE
wait_ack_message( &msg ); //wait for ACK_TEMPERATURE
serial_close(fd);
}
return 0;
}
主程序 发送 COMMAND_TEMPERATURE 消息, 等待 ACK_TEMPERATURE 返回消息, 从返回消息的内容中第一、二字节得到温度值,第三字节得到湿度值。
将C语言程序交叉编译后生成temperature_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 temperature_test
运行结果, 得到了当前温度和湿度:
Temperature: 25.0, Humidity:87
三、倾斜开关、水银开关(TILT SWITCH), 见下图
倾斜开关其实就是一种开关,开关上有一个玻璃管子,管子里有一个水银球。当开关倾斜,水银i球就会滚动。当开关倾斜到一定程度,水银球就会落到管子底部,把管子底部的两根电极接通。如果反向倾斜,则水银球离开管子底部,管子底部的两根电极将不通。因此,也称为水银开关。
倾斜开关可以用于监测货物有否翻倒等。
编一个Arduino程序,采用上例中的通信协议,监控开关状态,如有状态变化,通过串口发送消息到到主控板, 编译上传到ATmegaU32
Arduino程序等待 COMMAND_TEMPERATURE消息, 调用getTemperature() , 其中调用 DHT.read11()读取传感器数据。
如果读取数据成功,返回 ACK_TEMPERATURE消息,消息内容三个字节,第一个字节是温度的整数位、第二个字节是温度的小数第1位。第三字节是湿度。
编一个C语言主程序 temperature_test.c,采用消息协议,向Arduino发送COMMAND_TEMPERATURE消息送到,等待Arduino返回 ACK_TEMPERATURE消息, 读取其中的温度和湿度值打印出来。 交叉编译后生成temperature_test,用scp命令上传到开发板</p><p><pre name="code" class="cpp">#include <stdio.h>
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#define COMMAND_SWITCH 's'
int pinSwitch = 3; //pin 3 connects to switch
int lastValue = 0; // last value of pin
int checkTimes = 0; // check times for key jitter
void setup() {
MessageInit(57600); //init message < need message_protocol.ino >
pinMode(pinSwitch, INPUT); //set pinSwitch INPUT
lastValue = digitalRead(pinSwitch); //get last value
}
void loop() {
int value = digitalRead(pinSwitch); //read the switch
if (value != lastValue) { //if value changed
//eliminate key jitter: check 4 times
checkTimes = 0;
delay(100); //delay 100 ms
while ( value == digitalRead(pinSwitch) && checkTimes++ < 4 )
checkTimes++;
//if continous 4 times
if (checkTimes >= 4 ) {
unsigned char c = value & 0xFF; //change to unsigned char
MessageSend( COMMAND_SWITCH, &c, 1); //send message
lastValue = value;
}
}
delay(10); //delay in between reads for stability
}
编一个C语言主程序 tilt_test.c,采用消息协议,监听串口有否按键消息送到,打印出来, 交叉编译后生成tilt_test,用scp命令上传到开发板
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_SWITCH 's'
int test_switch() {
int fd; //file descriptor of serial port
message_t msg; //message object
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
//loop
while ( 1 ) {
if ( 1 == message_receive(&msg) ) { //if received message
if ( message_command(&msg) == COMMAND_SWITCH ) {
printf("switch value = %d\n", message_data(&msg, 0 ) ); //print value
fflush(stdout);
}
}
usleep(10*1000); //wait 10 milli-seconds
}
serial_close(fd);
}
return 0;
}
将C语言程序交叉编译后生成tilt_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 tilt_test
用手反复倾斜开关,观察水银球来回滚动,和屏幕输出结果:switch value = 1
switch value = 0
switch value = 1
水银球接通开关时,switch value = 0. 水银球不接通开关时, switch value = 1
四、激光发射器(Laser Emit), 见下图
编一个Arduino程序,采用消息协议,收到消息后,将D3设置为HIGH 或 LOW, 则激光将发射或关闭。 Arduino程序如下,请编译后上传到ATmegaU32
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#define COMMAND_LASER 'a'
int pinLaser = 3; //pin 3 connects to laser emit module
void setup() {
MessageInit(57600); //init message < need message_protocol.ino >
pinMode(pinLaser, OUTPUT); //set pinLaser OUTPUT
}
void loop() {
if ( MessageReceive() ) { //if receive message
if ( MessageCommand() == COMMAND_LASER ) {
int value = MessageData(0);
if (value == 1)
digitalWrite(pinLaser, HIGH);
else
digitalWrite(pinLaser, LOW);
MessageACK( COMMAND_LASER );
}
}
}
编一个C语言主程序 test_laser.c,采用消息协议,向Arduino发消息。
注意:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_LASER 'a'
int test_laser() {
int fd; //file descriptor of serial port
message_t msg; //message object
unsigned char value;
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
value = 1;
message_send( &msg, COMMAND_LASER, &value, 1); //send COMMAND_LASER message, value = 1
sleep(5);//wait 5 seconds
value = 0;
message_send( &msg, COMMAND_LASER, &value, 1); //send COMMAND_LASER message, value = 0
serial_close(fd);
}
return 0;
}
交叉编译后生成laser_test,用scp命令上传到开发板
将C语言程序交叉编译后生成laser_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 laser_test
运行结果: 程序一运行,则发射器发出一串激光,5秒后,激光关闭
五、光敏电阻接收器(Photoresistor), 见下图
编一个Arduino程序,采用消息协议,不断读取D4口的状态值,如有状态变化,通过串口发送COMMAND_SWITCH消息到到主控板。这个程序同时也接收消息,如果有COMMAND_LASER消息,则打开或关闭激光。
程序如下,请编译上传到ATmegaU32
#define COMMAND_LASER 'a'
#define COMMAND_SWITCH 's'
int pinLaser = 3; //pin 3 connects to laser emit module
int pinPhotoResistor = 4; //pin 4 connects to photoresistor module
int lastValue = 0; //last value of photoresistor
void setup() {
MessageInit(57600); //init message < need message_protocol.ino >
pinMode(pinLaser, OUTPUT); //set pinLaser OUTPUT
pinMode(pinPhotoResistor, INPUT); //set pinPhotoResistor INPUT
lastValue = digitalRead( pinPhotoResistor );
}
void loop() {
int value = digitalRead( pinPhotoResistor );
if ( value != lastValue ) // PhotoResistor status change
{
unsigned char c = value & 0xFF; //convert to unsigned char
MessageSend( COMMAND_SWITCH, &c, 1); //send COMMAND_SWITCH to linkit 7688
lastValue = value;
}
if ( MessageReceive() ) { //receive message
if ( MessageCommand() == COMMAND_LASER ) { //if is COMMAND_LASER
int value = MessageData(0);
if (value == 1)
digitalWrite(pinLaser, HIGH); //turn LASER on
else
digitalWrite(pinLaser, LOW); //turn LASER off
MessageACK( COMMAND_LASER );
return;
}
}
delay(1);
}
编一个C语言主程序 resistor_test.c,采用消息协议,首先打开激光,然后监测有否COMMAND_SWITCH消息送达,如有,则打印出来。同时,对通过的物体计数。
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
程序如下:
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_SWITCH 's'
#define COMMAND_LASER 'a'
int test_resistor() {
int fd; //file descriptor of serial port
message_t msg; //message object
unsigned char value;
int counter = 0;
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
value = 1;
message_send( &msg, COMMAND_LASER, &value, 1); //turn LASER on
//loop
while ( 1 ) {
if ( 1 == message_receive(&msg) ) { //if received message
if ( message_command(&msg) == COMMAND_SWITCH ) { //if is COMMAND_SWITCH
value = message_data(&msg, 0 ); //get value
if ( value == 0 )
counter++; //increase counter
//print it out
printf("switch value = %d, counter = %d\n", value, counter );
fflush(stdout);
}
}
usleep(10*1000); //wait 10 milli-seconds
}
serial_close(fd);
}
return 0;
}
将C语言程序交叉编译后生成 resistor_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 resistor_test
运行: 程序一运行,则发射器发出一串激光,将激光对准光敏电阻。当激光射在光敏电阻上时,光敏电阻的输出值为0. 当光敏电阻收不到激光时,光敏电阻的输出值将变为1.
试着用物体穿过激光,则 激光会被遮挡一次,光敏电阻的输出值先为0,再变成1,再变成0. 此时计数器加1. 并打印在屏幕上。
如此,则可以计数了,比如:可以用于门闸计算进门的人数;也可用于生产线上,对通过的物体计数。
运行结果:
switch value = 0, counter = 1
switch value = 1, counter = 1
switch value = 0, counter = 2
switch value = 1, counter = 2
switch value = 0, counter = 3
switch value = 1, counter = 3
。。。
六、红外线接收(IR RECEIVER), 见下图
每个人的家中都有N多个红外线遥控器。
红外线遥控的原理: 遥控器发出某个频率红外线(通常是38K), 这束红外线有时高、有时低,即以类似“10101100..."的编码方式发出。接收器收到这束红外线后,必须先解码,得到一组数字。这个数字就是遥控器发出的命令。
但是,红外线的编码是比较复杂且很不标准的。各个厂家有不同的编码标准,典型的厂商编码标准有SONY、SHARP、NEC、SANYO、SAMSUNG、PANASONIC、LG等等。一般的家电遥控器,都是用专用的遥控器专用IC芯片去实现编码和解码的,而且不同厂商的IC芯片还不一样。 所以遥控器很不通用。
在Arduino中,我们可以使用上图这个红外线接收器模块,利用Arduino的计算能力进行解码,而且不需依赖专用IC芯片,就可以支持各种厂商的编解码,使得各种遥控器都能遥控Arduino。
在MAC OS的操作:右键点击Arduino IDE的图标出菜单,选菜单项“显示包内容”, 进入 “Contents/Java/libraries"(这个文件夹就是ardunio的库文件夹了)
6.3 红外线学习程序
比如:我想用家中的电视机遥控器 遥控Arduino. 那么,首先要写一个红外线学习的Arduino程序,用于读取和记录遥控器的编码,如下:
//------------------------------------------------------------------------------
// Include the IRremote library header
#include <IRremote.h>
//------------------------------------------------------------------------------
int recvPin = 5; //IR receiver connects to pin 5
IRrecv irrecv(recvPin); //init IRrecv
unsigned char ir_type = 0; //IR type
unsigned int key_count = 0; //key count
unsigned long last_key = 0; // last key value
unsigned int repeat_count = 0; //repeat key count
//+=============================================================================
// print IR type string
void printIRType()
{
switch (ir_type) {
case NEC: Serial.print("NEC"); break ;
case SONY: Serial.print("SONY"); break ;
case RC5: Serial.print("RC5"); break ;
case RC6: Serial.print("RC6"); break ;
case DISH: Serial.print("DISH"); break ;
case SHARP: Serial.print("SHARP"); break ;
case JVC: Serial.print("JVC"); break ;
case SANYO: Serial.print("SANYO"); break ;
case MITSUBISHI: Serial.print("MITSUBISHI"); break ;
case SAMSUNG: Serial.print("SAMSUNG"); break ;
case LG: Serial.print("LG"); break ;
case WHYNTER: Serial.print("WHYNTER"); break ;
case AIWA_RC_T501: Serial.print("AIWA"); break ;
case PANASONIC: Serial.print("PANASONIC"); break ;
case DENON: Serial.print("DENON"); break ;
default: Serial.print("UNKNOWN"); break ;
}
}
//+=============================================================================
// Configure the Arduino
//
void setup ( )
{
irrecv.enableIRIn(); // Start the IR receiver
Serial.begin(57600); // Init Serial
Serial.println("please press keys on IR remote controller");
}
//+=============================================================================
// The repeating section of the code
//
void loop ( )
{
decode_results results; // Somewhere to store the results
if (irrecv.decode(&results)) // receive an IR code
{
//whether results has valid value
if ( results.decode_type != UNKNOWN && results.value != 0xFFFFFFFF ) {
//whether the same key is pressed
if (results.value == last_key ) {
repeat_count++;
} else {
last_key = results.value;
repeat_count = 0;
}
if ( repeat_count == 0 ) {
//print informations
if ( ir_type == 0 ) {
ir_type = results.decode_type; //save IR type
//print type
Serial.print("unsigned char ir_type = ");
Serial.print(ir_type);
Serial.print("; // ");
printIRType();
Serial.println("");
//print ir codes array statement
Serial.println("unsigned long ir_codes[] = { ");
}
//print IR value
Serial.print("\t0x");
Serial.print(results.value, HEX);
Serial.print(", //KEY ");
Serial.println(key_count++); //increase key count
} else if ( repeat_count == 3 ) {
//repeat 3 times will end current receive task
Serial.println("};");
ir_type = 0;
key_count = 0;
last_key = 0;
repeat_count = 0;
}
}
irrecv.resume(); // Prepare for the next value
}
delay(10); //wait a while for stability
}
这个Arduino程序只需用Arduino IDE上传到ATmega32U4即可, 不需要使用到Linkit 7688。
程序的用途是:当遥控器逐个按下时,记录下按键值,显示在Arduino的串口监视器窗口中。如果同一按键重复按二次,则忽略。如果同一按键重复按三次,则重新开始记录。
将程序编译上传到ATmega32U4, 运行,将电视机遥控器对着红外接收模块,逐个按下遥控器的各个按钮,最后一个按键重复按三次,运行结果如下:
unsigned char ir_type = 3; // NEC
unsigned long ir_codes[] = {
0x20DF08F7, //KEY 0
0x20DF8877, //KEY 1
0x20DF48B7, //KEY 2
0x20DFC837, //KEY 3
0x20DF28D7, //KEY 4
0x20DFA857, //KEY 5
0x20DF6897, //KEY 6
0x20DFE817, //KEY 7
0x20DF18E7, //KEY 8
0x20DF9867, //KEY 9 (最后一个键,要重复按三次)
};
如此,则得到一段代码, 其中:ir_type是遥控器编码厂商类型,ir_codes[]是一个数组,分别记录了第0 至 n个 按键的值。
6.4 红外线接收程序
编一个Arduino程序,采用消息协议,监控红外线接收状态,则发送COMMAND_IR_RECEIVE消息(内容为键值到主控板,程序如下:
注意:程序将使用message_protocol.ino模块,要把 message_protocol.ino 这个文件放在本Arduino项目文件夹中, 然后重新打开项目即可包含此模块
#include <IRremote.h>
#define COMMAND_IR_RECEIVE 'i'
int recvPin = 5; //IR receiver connects to pin 5
IRrecv irrecv(recvPin); //init IRrecv
//IR key codes
unsigned char ir_type = 3; // NEC
unsigned long ir_codes[] = {
0x20DF08F7, //KEY 0
0x20DF8877, //KEY 1
0x20DF48B7, //KEY 2
0x20DFC837, //KEY 3
0x20DF28D7, //KEY 4
0x20DFA857, //KEY 5
0x20DF6897, //KEY 6
0x20DFE817, //KEY 7
0x20DF18E7, //KEY 8
0x20DF9867 //KEY 9
};
void setup() {
MessageInit( 57600 ); // init message < need message_protocol.ino >
irrecv.enableIRIn(); // Start the IR receiver
}
void loop() {
unsigned char i;
decode_results results; // Somewhere to store the results
if (irrecv.decode(&results)) // receive an IR code
{
if ( results.decode_type == ir_type && results.value != 0xFFFFFFFF ) {
//find value in ir_codes array
for (i = 0; i < sizeof(ir_codes); i++) {
if (results.value == ir_codes[i]) {
MessageSend( COMMAND_IR_RECEIVE, &i, 1); //send message, content is key index
}
}
}
irrecv.resume(); // Prepare for the next value
}
delay(10); // delay in between reads for stability
}
Arduino程序中的 ir_type, ir_codes 就是从红外线学习程序的运行结果中复制来的, 注意:要把 ir_codes数组最后一个数据后的 逗号删去。
Arduino程序的作用是: 当收到红外线信号,在ir_codes数组中查找按键值。如找到,则向主控板发送一个 COMMAND_IR_RECEIVE消息,消息内容是 按键在数组中的序号
将Arduino程序编译上传到ATmega32U4
/*
* ir_test.c
*
*/
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_IR_RECEIVE 'i'
int main() {
int fd; //file descriptor of serial port
message_t msg; //message object
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
//loop
while ( 1 ) {
if ( 1 == message_receive(&msg) ) { //if received message
if ( message_command(&msg) == COMMAND_IR_RECEIVE ) {
printf("IR key index = %d\n", message_data(&msg, 0 ) ); //print key index
fflush(stdout);
}
}
usleep(10*1000); //wait 10 milli-seconds
}
serial_close(fd);
} else {
printf("open serial fail\n");
}
return 0;
}
将C语言程序交叉编译后生成 ir_test,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,运行 ir_test
运行: 程序后,当用遥控器对这开发板按键时,则打印出按键结果, 效果如下:IR key index = 1
IR key index = 2
IR key index = 3
。。。
六、红外线发射(IR EMISSION), 见下图
模块上有一个红外线发射二极管
编一个Arduino程序,采用消息协议,接收COMMAND_IR_SEND消息,根据消息内容中的按键序号,翻译为红外线值,发送红外线。程序如下:
#include <IRremote.h>
#define COMMAND_IR_SEND 'r'
IRsend irsend; //note: for ATmega32U4, IR send module must connects to pin 13
//IR key codes
unsigned char ir_type = 3; // NEC
unsigned long ir_codes[] = {
0x20DF08F7, //KEY 0
0x20DF8877, //KEY 1
0x20DF48B7, //KEY 2
0x20DFC837, //KEY 3
0x20DF28D7, //KEY 4
0x20DFA857, //KEY 5
0x20DF6897, //KEY 6
0x20DFE817, //KEY 7
0x20DF18E7, //KEY 8
0x20DF9867 //KEY 9
};
void setup() {
MessageInit( 57600 ); // init message < need message_protocol.ino >
}
int sendIR(unsigned char index) {
if (index >= sizeof(ir_codes))
return 0;
switch (ir_type) {
case NEC: irsend.sendNEC(ir_codes[index], 32); return 1;
case SONY: irsend.sendSony(ir_codes[index], 32); return 1;
case RC5: irsend.sendRC5(ir_codes[index], 32); return 1;
case RC6: irsend.sendRC6(ir_codes[index], 32); return 1;
case DISH: irsend.sendDISH(ir_codes[index], 32); return 1;
case SHARP: irsend.sendSharp(ir_codes[index], 32); return 1;
case JVC: irsend.sendJVC(ir_codes[index], 32, false); return 1;
case SANYO: return 0;
case MITSUBISHI: return 0;
case SAMSUNG: irsend.sendSAMSUNG(ir_codes[index], 32); return 1;
case LG: irsend.sendLG(ir_codes[index], 32); return 1;
case WHYNTER: irsend.sendWhynter(ir_codes[index], 32); return 1;
case AIWA_RC_T501: irsend.sendAiwaRCT501(ir_codes[index]); return 1;
case PANASONIC: irsend.sendPanasonic(0, ir_codes[index]); return 1; //?address
case DENON: irsend.sendDenon(ir_codes[index], 32); return 1;
default: return 0;
}
return 0;
}
void loop() {
if ( MessageReceive() ) { //if message received
if ( MessageCommand() == COMMAND_IR_SEND ) {
unsigned char index = MessageData(0); //get index of ir_codes from message data(0)
if ( sendIR(index) ) //send IR
MessageACK( COMMAND_IR_SEND ); //if send OK, response ACK message
else
MessageNAK( COMMAND_IR_SEND ); //if send fail, response NAK message
}
}
}
Arduino程序的作用是: 当收到COMMAND_IR_SEND消息,在消息内容中取得按键编号,发送红外线。如发送成功,返回ACK消息。如不成功返回NAK消息。
将Arduino程序编译上传到ATmega32U4
编一个C语言主程序 ir_send.c,采用消息协议,向ATmega32U4发送COMMAND_IR_SEND消息,则可以控制它发送红外线
注:项目中要使用到 串口函数模块serial.c 和 消息协议模块 message_protocol.c
#include <stdio.h>
#include <unistd.h>
#include "serial.h"
#include "message_protocol.h"
#define COMMAND_IR_SEND 'r'
int main(int argc, char **argv) {
int fd; //file descriptor of serial port
message_t msg; //message object
unsigned char value;
if (argc > 1 ) {
value = atoi(argv[1]);
} else {
printf("Usage: ir_send <key>\n");
return 1;
}
fd = serial_open(0, 57600);//open serial port 0, /etc/ttyS0
if ( fd > 0 ) {
message_init( &msg, fd, 57600 ); //init message with fd, set baud rate
message_send( &msg, COMMAND_IR_SEND, &value, 1); //send COMMAND_IR_SEND message
serial_close(fd);
}
return 0;
}
使用方法举例: ir_send 0 即红外线发送 第0个按键
将C程序交叉编译后生成ir_send,用scp命令上传到开发板
SSH登入 Linkit 7688 DUO开发板,将红外发射头对着电视机,运行ir_send:
ir_send 0
则可以看到,电视机接收到红外线信号,作出了反应。
ir_send 1
则可以看到,电视机再次接收到红外线信号,作出了反应。
呵呵, 可以遥控电视机了。