2015-06-06 57 views
1

我正在進行個人家庭自動化項目。Arduino系列與Debian一起工​​作正常,但與Raspbian掛起

在服務器端,我有一個Arduino臨贈送與:

  • 上銷2
  • 一個433兆赫TX模塊上銷3
  • 上銷DHT22探針433兆赫RX模塊圖4(用10k上拉)
  • 上銷5(用10k上拉)一個DHT22探針

我有兩個完全相同的這些模塊的;一個是無線電中繼(和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,我可以使用該系統,就像我想,它的工作原理:

[email protected]:~/dev/probe$ gcc probe.c -o probe 
[email protected]:~/dev/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 1 
1;1;1;23.60;43.10 
[email protected]:~/dev/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 2 
1;1;2;23.60;38.50 
[email protected]:~/dev/probe$ ./probe --device /dev/ttyUSB0 --proto radio1 --length 24 --value 5396 
2;1;24;5396;OK 
[email protected]:~/dev/probe$ ./probe --device /dev/ttyUSB0 --proto radio1 --length 24 --value 5393 
2;1;24;5393;OK 

在Raspbian,第一次調用工作,但第二個掛我的終端和我要做的CTRL + C :

[email protected]:~/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 1 
1;1;1;23.90;39.00 
[email protected]:~/probe$ ./probe --device /dev/ttyUSB0 --module 1 --probe 2 
^C 
+0

我已經更換,在Arduino的一側,條件降低了問題: '如果(Serial.available()== 9 && readCommand ()){'with'if(Serial.available()> = 9 && readCommand()){'。它不會停止,但仍然會在Raspbian下響應80%的時間,而在Debian下100%(OK)下工作。 – Moonchild

回答

0

我發現了!

看起來像在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(); 
    } 

    // ... 
} 
相關問題