3

もともと、AutoHotkeyを使用して Arduino と通信していましたが、Arduino に何も送信しない状態が数時間続くと (Arduino は 10 秒ごとに「ハートビート」を送信しました)、接続がフリーズまたは失敗することがわかりました。

現在、RS-232 ライブラリを使用して C++ プログラムからシリアル接続を介して Arduino を制御しようとしています。

しかし、私は同じ問題を抱えています。プログラムは 20 秒ごとに Arduino に ping を送信し、Arduino は小さな文字列の情報を報告することになっています。数時間後、接続が切断され、私の C++ プログラムは応答なしで ping を実行したままになります。Arduinoにはウォッチドッグがあり、接続が機能していないときにまだ機能していることを確認できるので、私の問題はシリアルに固有のタイムアウトにあると思います...接続がアクティブに使用されていることを除いて..

シリアル接続を維持するために何をする必要があるかを理解していただければ幸いです。コンピューターはArduino 24/7にデータを送信できる必要があります。

でコンパイルしCode::Blocks、Windows 7 でプログラムを実行しています。

私は C++ や C にあまり詳しくないので、プログラムで私が行っている他のばかげたことを見つけたら、お知らせください。

main.cpp

/**************************************************

  File: main.cpp
  Purpose: Simple demo that receives characters from
           the serial port and print them on the
           screen.

**************************************************/

#include <stdlib.h>
#include <iostream>

#ifdef _WIN32
    #include <Windows.h>
#else
    #include <unistd.h>
#endif

#include "rs232.h"

using namespace std;

int main()
{
    int debug = 0;
    int i = 0, n,
    cport_nr = 5,        /* /dev/ttyS5 (COM6 on Windows) */
    bdrate = 9600;       /* 9600 baud */

    unsigned char buf[4096];

    if(OpenComport(cport_nr, bdrate))
    {
        cout << "Can not open comport\n";
        return(0);
    }

    while(1)
    {
        if (debug)
        {
            printf("Entering While(1) loop. \n");
        }

        n = PollComport(cport_nr, buf, 4095);

        if(n > 0)
        {
            buf[n] = 0;   /* always put a "null" at the end of a string! */

            /* for(i=0; i < n; i++)
            {
                if(buf[i] < 32)  // replace unreadable control-codes by dots
                {
                  buf[i] = '.';
                }
            } */

            //printf("\n\n\nreceived %i bytes: %s\n\n", n, (char *)buf);
            cout << endl << endl << endl << (char *)buf;
        }

        if (SendByte(cport_nr, 83))
        {
            printf("\n\nSending data didn't work. \n\n");
        }
        else
        {
            cout << "\nSent [S]\n";
        }

        i = 0;

        #ifdef _WIN32
            Sleep(10000);  /* It's ugly to use a sleeptimer, in a real program, change
                              the while-loop into a (interrupt) timerroutine. */
        #else
            usleep(10000000);  /* Sleep for 100 milliSeconds */
        #endif
    }
    return(0);
}

Arduinoファイル

//
// SuiteLock v.2.1a
// By: Chris Bero (bigbero@gmail.com)
// Last Updated: 11.4.2012
//

#include <Servo.h>
#include <avr/wdt.h>

// Pin Constants:
const int servoPin = 9;
const int doorbtn = 3;

// Not sure if I'm still going to use these...
const int ledGND = 4;
const int ledVCC = 5;
const int servDelay = 600; // The delay allowing for the servo to complete an action.

//Variables:
int doorState = 0;  // The value returned by the door button (0 or 1).
int servState = 90;  // The position of the servo in degrees (0 through 180).
unsigned long prevMillis = 0;
unsigned long progCycles = 0;
int serialByte = 0;
int lastSerial = 0;
int smallBlink = 0;
bool dostatus = false; // Determine whether to send sys status.
Servo serv;

// Set up the environment.
void setup()
{
    wdt_enable(WDTO_4S);
    pinMode(doorbtn, INPUT);
    pinMode(ledGND, OUTPUT);
    pinMode(ledVCC, OUTPUT);
    pinMode(servoPin, OUTPUT);
    digitalWrite(ledGND, LOW);
    serv.attach(servoPin);
    Serial.begin(9600);
    prevMillis = millis();
}

////////////////////////////////////////////////
// Statuser - Sends system status to Serial
/////////////////////////////////////////////
int statuser ()
{
    wdt_reset();
    Serial.println("[Start]"); //Start Of Transmission
    delay(15);
    unsigned long currentMillis = millis();
    refresh();
    Serial.print("\tTime Alive: ");
    int hr = ((currentMillis/1000)/3600);
    int mn = (((currentMillis/1000)-(hr*3600))/60);
    int sc = ((currentMillis/1000)-(hr*3600)-(mn*60));
    Serial.print(hr);
    Serial.print(":");
    Serial.print(mn);
    Serial.print(":");
    Serial.println(sc);
    Serial.print("\tNum of Program Cycles: ");
    Serial.println(progCycles);
    Serial.print("\tAvg Cycles per Second: ");
    int cps = (progCycles/(currentMillis/1000));
    Serial.println(cps);
    Serial.print("\tDoorState: ");
    Serial.println(doorState);
    Serial.print("\tServo Position: ");
    Serial.println(servState);
    Serial.print("\tLast Serial Byte: ");
    Serial.println(lastSerial);
    delay(15);
    Serial.println("[End]"); //End Of Transmission
    return(0);
}

////////////////////////
// Lock the door.
/////////////////////
int locker()
{
    wdt_reset();

    // Check the button states.
    refresh();

    // Make sure the door is closed.
    do
    {
        wdt_reset();
        delay(500);
        refresh();
    } while(doorState == LOW);

    // Turn on the locking LED during the servo movement.
    digitalWrite(ledVCC, HIGH);

    wdt_reset();

    // Tell the servo to turn to 20 degrees.
    serv.write(20);

    // Give the servo time to complete the turn.
    delay(servDelay);

    wdt_reset();

    // Turn the servo opp direction to reset.
    serv.write(90);

    // Wait for the servo to reach it's reset point.
    delay(servDelay);

    // Turn off the cool little LED.
    digitalWrite(ledVCC, LOW);

    // Call parents for 11pm checkup and tell them everything's A-OK.
    return(0);
}

/////////////////////////
// Unlock the door.
//////////////////////
int unlocker ()
{
    wdt_reset();

    // Check the pin states.
    refresh();

    // Turn on the status LED.
    digitalWrite(ledVCC, HIGH);

    wdt_reset();

    // Turn servo to 170 degrees to unlock the door.
    serv.write(170);

    // Wait for servo motion to complete.
    delay(servDelay);

    wdt_reset();

    // Reset the servo to 90 degrees.
    serv.write(90);

    // Wait for reset motion to complete.
    delay(servDelay);

    // Turn off LED.
    digitalWrite(ledVCC, LOW);

    return(0);
}

///////////////////////////////
// Refresh button states.
/////////////////////////////
void refresh ()
{
    wdt_reset();
    doorState = digitalRead(doorbtn);
    servState = serv.read();
}

///////////////////////
// Main function.
////////////////////
void loop()
{
    wdt_reset();

    // Blink the LED every so many turn overs of the function.
    if (smallBlink == 5)
    {
        smallBlink = 0;
        digitalWrite(ledVCC, HIGH);
        delay(300);
        digitalWrite(ledVCC, LOW);
    }

    // Status.
    if(dostatus == true)
    {
        unsigned long currentMillis = millis();
        if ((currentMillis - prevMillis) > 4000)
        {
            prevMillis = currentMillis;
            statuser();
        }
    }

    // Refresh button states.
    refresh();

    // Is the door closed and not locked? *Gasp*
    if ((doorState == LOW))
    {
        // Fix it.
        while (doorState == LOW)
        {
            wdt_reset();
            delay(500);
            refresh();
        }
        locker();
    }

    // Check for available communications.
    if (Serial.available() > 0)
    {
        // Reset the serialByte, done for debugging.
        serialByte = 0;
        wdt_reset();
        // Read the serialByte.
        serialByte = Serial.read();
        lastSerial = serialByte;
    }

    // Act on the byte data.
    if (serialByte == 'U')
    {
        // Let someone in.
        unlocker();
        // Wait for the door to change states.
        delay(1000);
    }
    if (serialByte == 'L')
    {
        locker();
        delay(1000);
    }
    if (serialByte == 'S')
    {
        statuser();
        delay(200);
    }

    // Clean serialByte for debugging.
    serialByte = 0;

    // Count through program cycles.
    progCycles++;
    smallBlink++;
}

C++ プログラムを調整して、comport を開き、「S」を送信してから、comport を閉じて待機するようにしました。次に、ポートを開閉し続けるように、手順をループさせました。これにより、接続が数時間のマークに達したり、タイムアウトになったりするのを防ぐことができれば幸いです。代わりに、プログラムは 1 時間正常にループし、突然 COM ポートを開くことができませんでした...

CrazyCasta が正しく、バグがあるのは私の Arduino のラップトップへの接続だけである場合、最初にコンピューターを再起動せずに接続をリセットする方法はありますか?

4

1 に答える 1

1

CrazyCasta が言ったように、それはハードウェアの問題でした。Arduino とコンピューターの間の 9 フィート (2.7 m) の USB 延長コードを取り外すことで、この問題を解決できました。

今朝の時点で、接続は 10 時間有効であり、これは以前のテストよりも 7 時間長くなっています。これが修正されたと言っても過言ではないことを願っています。

于 2012-11-05T14:09:15.317 に答える