gpt4 book ai didi

c - Arduino 系列在 Debian 上运行良好,但在 Raspbian 上挂起

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:28:41 25 4
gpt4 key购买 nike

我正在从事个人家庭自动化项目。

在服务器端,我有一个 Arduino Pro Mini:

  • 引脚 2 上的 433 MHz TX 模块
  • 引脚 3 上的 433 MHz RX 模块
  • 引脚 4 上的 DHT22 探针(带有 10k 上拉电阻)
  • 引脚 5 上的 DHT22 探针(带有 10k 上拉电阻)

我有两个完全相同的模块;一个将是 radio 中继(和 DHT“服务器”),另一个将是辅助 DHT“服务器”。

当它通过 FTDI 电缆连接到我的笔记本电脑 (Debian Wheezy) 时,它可以读取本地探测器并通过我编写的 C 程序打开/关闭墙上的插头。我想在 Raspberry Pi 上使用它。但是在 Raspberry Pi 上(USB 上使用相同的 FTDI 电缆),它执行我发送的第一个命令然后挂起我的终端,迫使我使用 CTRL+C。

这是 Arduino 端的草图(标题):

/**
* probe.h
*
* @author David Mézière <...>
*/

/**
* DHT probe result
*
*/
struct Probe {
float temperature;
float humidity;
};

主文件:

/**
* probe.ino
*
* @author David Mézière <...>
*/

#include "probe.h"

/**
* Uses DHT sensor library, from Adafruit.
* @see https://github.com/adafruit/DHT-sensor-library
*/
#include <DHT.h>

/**
* Uses RC Switch library, from sui77.
* @see https://github.com/sui77/rc-switch
*/
#include <RCSwitch.h>

// Pinout definitions
#define TX 2 // 433 MHz transmitter pin number
#define RX 3 // 433 MHz receiver pin number
#define PROBE1 4 // First DHT22 probe pin number
#define PROBE2 5 // Second DHT22 probe pin number
#define LED 13 // On-board status LED pin number

RCSwitch radio = RCSwitch();

// DHT probes definition
DHT dht1(PROBE1, DHT22);
DHT dht2(PROBE2, DHT22);

// Incomming command buffer
byte cmd[9];

/**
* Setup
*
* @return void
*/
void setup()
{
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);

Serial.begin(9600);
Serial.setTimeout(1000); // doesn't fix the problem

// Attach receiver to interrupt 1, meaning pin 3
radio.enableReceive(1);

radio.enableTransmit(TX);

dht1.begin();
dht2.begin();

// Debug: Internal LED will blink 3 times rapidly to show when a reboot occurs.
for (int i = 0; i < 3; i++) {
digitalWrite(LED, HIGH);
delay(250);
digitalWrite(LED, LOW);
delay(250);
}
}

/**
* Loop
*
* @return void
*/
void loop()
{
if (Serial.available() == 9 && readCommand()) {

// Lights-up internal LED to show when a command has been executed
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
}
}

/**
* Query probe
*
* Query provided [dht] probe until [retry] times for both temperature and humidity.
*
* @param DHT dht Pointer to DHT object
* @param int retry Number of tries
* @return Probe Probe result (float temperature in °C, float humidity in %)
*/
Probe queryProbe(DHT* dht, int retry)
{
Probe probe;

// Query DHT22 probe for temperature, a maximum of [retry] times.
for (int t = 0; t < retry; t++) {
probe.temperature = dht->readTemperature(false);
if (!isnan(probe.temperature)) {
break;
}
delay(50);
}

// Query DHT22 probe for humidity, a maximum of [retry] times.
for (int h = 0; h < retry; h++) {
probe.humidity = dht->readHumidity();
if (!isnan(probe.humidity)) {
break;
}
delay(50);
}

return probe;
}

/**
* Read command
*
* If serial buffer contains 2 bytes, move them to a local buffer and return true. else return false.
*
* @return boolean
*/
boolean readCommand()
{
// Reads the current buffer
Serial.readBytes(cmd, 9);

// Calculates the check sum of payload
int sum = cmd[2] ^ cmd[3] ^ cmd[4] ^ cmd[5] ^ cmd[6] ^ cmd[7];

// Checking header and checksum a header of 0xBA 0xB1 means DHT query
if (cmd[0] == 0xBA && cmd[1] == 0xB1 && cmd[8] == sum) {

unsigned int module = cmd[2];
unsigned int probe = (cmd[4] << 24) + (cmd[5] << 16) + (cmd[6] << 8) + cmd[7];

Probe result;

switch (module) {

case 1:
// Selects the right probe
if (probe == 1) {
result = queryProbe(&dht1, 3);
} else if (probe == 2) {
result = queryProbe(&dht2, 3);
}

// Send status repport to client
Serial.print("1;");
Serial.print(module);
Serial.print(";");
Serial.print(probe);
Serial.print(";");
Serial.print(result.temperature);
Serial.print(";");
Serial.println(result.humidity);
Serial.flush(); // Doesn't fix the problem
break;
}

return true;

// A header of 0xBA 0xB2 means rf wall plugs query
} else if (cmd[0] == 0xBA && cmd[1] == 0xB2 && cmd[8] == sum) {

unsigned int proto = cmd[2];
unsigned int length = cmd[3];
unsigned int value = (cmd[4] << 24) + (cmd[5] << 16) + (cmd[6] << 8) + cmd[7];
radio.send(value, length);

// Send status repport to client
Serial.print("2;");
Serial.print(proto);
Serial.print(";");
Serial.print(length);
Serial.print(";");
Serial.print(value);
Serial.print(";");
Serial.println("OK");
Serial.flush(); // Doesn't fix the problem

return true;

} else {
Serial.println("KO");
Serial.flush(); // Doesn't fix the problem

return false;
}
}

在客户端:

/** 
* probe.c
*
* @author David Mézière <...>
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <getopt.h>

const char* device;
static int module = 0; // uint_8 ?
static int probe = 0; // uint_8 ?
const char* proto;
static int length = 0; // uint_8 ?
static int value = 0; // uint_32 ?
static int verbose = 0; // uint_8 ?

void help()
{
printf("usage:\n");
printf("\n");
printf("probe [options] [arguments]\n");
printf("\n");
printf("options:\n");
printf(" -h|--help: Displays this help and exit\n");
printf(" -v|--verbose: Be more verbose\n");
printf("\n");
printf("arguments:\n");
printf(" -d|--device: string Serial device to use (ex: /dev/ttyUSB0)\n");
printf(" -m|--module: integer DHT22 module to query\n");
printf(" -p|--probe: integer DHT22 probe to query\n");
printf(" -r|--proto: string Radio / IR protocol\n");
printf(" -l|--length: integer Radio / IR value length in bits\n");
printf(" -a|--value: integer Radio / IR value\n");
printf("\n");
printf("examples:\n");
printf(" probe --device /dev/ttyUSB0 --module 1 --probe 1 : Will query first DHT22 probe of first module\n");
printf(" probe --proto radio1 --length 12 --value 5393 : Will send value 5393 on 12 bits over the air using protocol 1\n");
printf(" probe --proto ir11 --length 64 --value 3772793023 : Will send value 3772793023 on 64 bits by infra red using protocol 11\n");
}

void parseArgs(int argc, char **argv)
{
int c;

while (1) {
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"module", required_argument, 0, 'm'},
{"probe", required_argument, 0, 'p'},
{"proto", required_argument, 0, 'r'},
{"length", required_argument, 0, 'l'},
{"value", required_argument, 0, 'a'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;

c = getopt_long(argc, argv, "d:hm:p:v", long_options, &option_index);

/* Detect the end of the options. */
if (c == -1) {
break;
}

switch (c) {
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0) {
break;
}
printf("option %s", long_options[option_index].name);
if (optarg) {
printf (" with arg %s", optarg);
}
printf("\n");
break;

case 'd':
device = optarg;
break;

case 'h':
help();
exit(0);
break;

case 'm':
module = atoi(optarg);
break;

case 'p':
probe = atoi(optarg);
break;

case 'r':
proto = optarg;
break;

case 'l':
length = atoi(optarg);
break;

case 'a':
value = atoi(optarg);
break;

case 'v':
verbose = 1;
break;

case '?':
/* getopt_long already printed an error message. */
break;

default:
abort();
}

}

/* Print any remaining command line arguments (not options). */
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc) {
printf("%s ", argv[optind++]);
}
putchar('\n');
}

if (&device[0] == '\0') {
fprintf(stderr, "--device is mandatory\n");
exit(1);
} else if (verbose) {
printf("Device: %s\n", device);
}

if (verbose) {
printf("Querying probe %i of module %i.\n", probe, module);
}
}

void initSerial(int fd)
{
struct termios toptions;

/* get current serial port settings */
tcgetattr(fd, &toptions);
/* set 9600 baud both ways */
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);
/* 8 bits, no parity, no stop bits */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
/* Canonical mode */
toptions.c_lflag |= ICANON;
/* commit the serial port settings */
tcsetattr(fd, TCSANOW, &toptions);
}

int main(int argc, char **argv)
{
// Parses command line arguments
parseArgs(argc, argv);

int fd, n, i;
char buf[64] = "temp text";

/* open serial port */
fd = open(device, O_RDWR | O_NOCTTY);

if (verbose) {
printf("Device %s opened as %i\n", device, fd);
}

/*
* Note: Most Arduinos models will reboot upon connection, and they need
* some time for it. I use a pro/mini that doesn't, so i commented it out.
*/
// usleep(3500000);

// Sets the serial port settings (9600 bps, 8 bits, no parity, no stop bits)
initSerial(fd);

/**
* 72 bits
* | Header | Param 1 | Param 2 | Param 3 | sum |
* | 16 b | 8 b | 8 b | 32 b | 8 b |
* Cas 1 : Requête DHT | 0xba 0xb1 | module | 0x00 | sonde | sum |
* Cas 2 : Requête radio | 0xba 0xb2 | proto | length | value | sum |
* Cas 3 : Requête IR | 0xba 0xb3 | proto | length | value | sum |
*/

unsigned char oBuf[9];

// printf("%s\n", proto);
// printf("%i\n", length);

if (module > 0 && probe > 0) {
if (verbose) {
printf("DHT mode\n");
}
oBuf[0] = 0xBA;
oBuf[1] = 0xB1; // DHT query
oBuf[2] = module;
oBuf[3] = 0x00;
oBuf[4] = (probe >> 24) & 0xFF;
oBuf[5] = (probe >> 16) & 0xFF;
oBuf[6] = (probe >> 8) & 0xFF;
oBuf[7] = probe & 0xFF;
oBuf[8] = oBuf[2];
oBuf[9] = '\n';

// Calculates the XOR sum
for (i = 3; i < 8; i++) {
oBuf[8] ^= oBuf[i];
}

// sprintf(oBuff, "%c%c%c%c%c%c", 0xba, 0xb1, module, 0x00, probe, sum);
} else if (strcmp((const char*)proto, "radio1") == 0 && length > 0) {
if (verbose) {
printf("Radio mode\n");
}
oBuf[0] = 0xBA;
oBuf[1] = 0xB2; // Radio query
oBuf[2] = 0x01; // Protocol 1
oBuf[3] = length;
oBuf[4] = (value >> 24) & 0xFF;
oBuf[5] = (value >> 16) & 0xFF;
oBuf[6] = (value >> 8) & 0xFF;
oBuf[7] = value & 0xFF;
oBuf[8] = oBuf[2];
oBuf[9] = '\n';

// Calculates the XOR sum
for (i = 3; i < 8; i++) {
oBuf[8] ^= oBuf[i];
}
} else {
if (verbose) {
printf("Unknown mode\n");
}

}

/* Send the buffer */
write(fd, oBuf, 9);

/* Receive string from Arduino */
n = read(fd, buf, 64);

/* insert terminating zero in the string */
buf[n] = 0;

if (verbose) {
printf("%i bytes read, buffer contains: %s\n", n, buf);
} else {
printf("%s", buf);
}

return 0;
}

我只使用 gcc probe.c -o probe 编译它。

在 Debian 上,我可以随心所欲地使用这个系统,它工作正常:

dmeziere@portable2-wlan:~/dev/probe$ gcc probe.c -o probe
dmeziere@portable2-wlan:~/dev/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 1
1;1;1;23.60;43.10
dmeziere@portable2-wlan:~/dev/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 2
1;1;2;23.60;38.50
dmeziere@portable2-wlan:~/dev/probe$ ./probe --device /dev/ttyUSB0 --proto radio1 --length 24 --value 5396
2;1;24;5396;OK
dmeziere@portable2-wlan:~/dev/probe$ ./probe --device /dev/ttyUSB0 --proto radio1 --length 24 --value 5393
2;1;24;5393;OK

在 Raspbian 上,第一个调用有效,但第二个调用挂起我的终端,我必须执行 CTRL+C:

dmeziere@raspberrypi:~/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 1
1;1;1;23.90;39.00
dmeziere@raspberrypi:~/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 2
^C

最佳答案

我找到了!

似乎在 Raspbian 上,通信被 NULL 字符终止。但不是在 Debian 上。这个 NULL 字符污染了我对传入缓冲区长度的计算。所以我最终在 Arduino 方面压制了它:

boolean readCommand()
{
// Reads the current buffer
Serial.readBytes(cmd, 9);

// If sender sends a null character, remove it.
int test = Serial.peek();
if (test == 0x00) {
test = Serial.read();
}

// ...
}

关于c - Arduino 系列在 Debian 上运行良好,但在 Raspbian 上挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30686789/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com