Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用串行通信在python和arduino之间进行同步_Python_Arduino_Serial Port_Synchronization - Fatal编程技术网

使用串行通信在python和arduino之间进行同步

使用串行通信在python和arduino之间进行同步,python,arduino,serial-port,synchronization,Python,Arduino,Serial Port,Synchronization,我有一个应用程序,我需要: 使用arduino将伺服电机移动到某个位置,并在该位置停止 让python控制的摄像头在该位置获取图像 获取图像时,伺服应移动到对称位置 该序列重复N次 所以我尝试使用串行通信来同步arduino和python代码。在arduino端,当伺服到达某个位置时,它使用串行通信向python代码发送一个字符串。根据到达的位置,字符串为“交叉”或“Co”。arduino应等待python代码通过串行通信发送字符串“Ok”(图像采集后)。收到该字符串后,arduino应启动伺服

我有一个应用程序,我需要:

  • 使用arduino将伺服电机移动到某个位置,并在该位置停止
  • 让python控制的摄像头在该位置获取图像
  • 获取图像时,伺服应移动到对称位置
  • 该序列重复N次

    所以我尝试使用串行通信来同步arduino和python代码。在arduino端,当伺服到达某个位置时,它使用串行通信向python代码发送一个字符串。根据到达的位置,字符串为“交叉”或“Co”。arduino应等待python代码通过串行通信发送字符串“Ok”(图像采集后)。收到该字符串后,arduino应启动伺服,使其移动到另一个位置

    在python代码端,我读取串行数据,并根据接收到的字符串(交叉或共):

  • 定义了一个字符串名
  • 使用相机获取图像
  • 图像将被保存或附加到列表中
  • 字符串“Ok”被发送到arduino 代码附在下面

    问题是我无法正确同步伺服位置和图像采集。伺服只是在两个位置之间来回运行,似乎没有从串行通信中读取任何字符串。然后它就永远不会停在某个位置。然而,arduino代码确实向python代码发送“Cross”和“Co”,python代码确实能够读取它们并获取和保存图像,但通常使用错误的名称。让arduino代码在每个位置等待足够长的时间不是一个解决方案,因为我需要一个合适的图像采集频率。
    因此,我想知道同步这两个代码的最佳方法是什么,并确保我的图像的正确名称将对应于伺服的正确位置

    提前感谢您提供的任何链接或想法

    格雷格

    阿杜伊诺代码 `

    #包括
    //伺服
    伺服myservo;//创建伺服对象以控制伺服
    //大多数电路板上可以创建12个伺服对象
    int pos=0;//变量来存储伺服位置
    //摄像机
    常数int CameraPin=53;//摄像机触发的次数
    int CameraState=低;//用于设置LED的LED状态
    常数int ledPin=13;//LED引脚的编号
    字符串Str=“c”;
    无效设置(){
    myservo.attach(9);//将针脚9上的伺服连接到伺服对象
    //将数字LED引脚设置为输出:
    pinMode(CameraPin,输出);
    //将数码相机引脚设置为输出:
    引脚模式(LED引脚,输出);
    //串行通信
    Serial.begin(9600);
    Serial.println(“就绪”);
    }
    void循环(){
    Serial.flush();
    //转到同一位置并等待
    ServoCo(15);//转到Co位置
    Serial.println(“Co”);//将信号Co发送到python
    而(!Serial.available()){}//等待python发送获取的数据
    当((Serial.available()在
    loop()
    函数中时,您已经实现了您的软件,因为该函数将作为控制台软件中的
    main()
    执行一次

    由于Arduino(C语言)必须通过串行链路与计算机(Python语言)通信,因此一个有效的解决方案是使用状态机原则

    步骤1-定义所需状态列表以及要达到的位置数

    一个简单的
    enum e_State
    允许定义列表

    对于要到达的两个位置,使用枚举e_Pos

    步骤2-定义启动参数

    要在
    loop()
    调用之间存储持久数据,
    static
    变量 使用的是:

    要临时存储下一个状态,请添加
    eState NextState

    loop()
    函数的输入处,
    NextState=LoopState;
    to 默认情况下保持相同的状态

    步骤3-定义状态机算法

    void loop() {
    
    static eState LoopState = STATE_START; // to store the current state
    static ePos ServoPos = FIRST_POS;  // to store the selected position
    
        eState NextState = LoopState;
    
        switch (LoopState) {
        case STATE_START:
            ServoPos = FIRST_POS;
            NextState = STATE_MOVE_POS;
            break;
        case STATE_MOVE_POS:
            NextState = STATE_SEND_CMD;
            break;
        case STATE_SEND_CMD:
            NextState = STATE_WAIT_ACK;
            break;
        case STATE_WAIT_ACK:
            // NextState = STATE_MOVE_POS;
            break;
        default:
            // when undefined state, restart
            NextState = STATE_START;
        }
        // define the state for the next loop
        LoopState = NextState;
    }
    
    步骤4-使用所选的
    ServoPos
    管理
    状态移动位置的操作

    switch (ServoPos) {
    case FIRST_POS:
        ServoCo(15); // go to 'Co' position
        break;
    case SECOND_POS:
        ServoCross(15); // go to 'Cross' position
        break;
    };
    NextState = STATE_SEND_CMD; // when reached, send serial message
    
    Serial.flush();   // clear the serial buffer
    if (ServoPos == FIRST_POS) {
        Serial.println("Co"); //send signal 'Co' to python
    }
    else {
        Serial.println("Cross"); //send signal 'Cross' to python
    }
    NextState = STATE_WAIT_ACK;
    
    步骤5-根据到达的
    伺服位置
    管理
    状态_SEND_CMD
    的操作

    switch (ServoPos) {
    case FIRST_POS:
        ServoCo(15); // go to 'Co' position
        break;
    case SECOND_POS:
        ServoCross(15); // go to 'Cross' position
        break;
    };
    NextState = STATE_SEND_CMD; // when reached, send serial message
    
    Serial.flush();   // clear the serial buffer
    if (ServoPos == FIRST_POS) {
        Serial.println("Co"); //send signal 'Co' to python
    }
    else {
        Serial.println("Cross"); //send signal 'Cross' to python
    }
    NextState = STATE_WAIT_ACK;
    
    步骤6-通过查找确认“OK”来管理
    状态等待确认的操作

    (可选)添加比较
    if(Str==“OK”)
    以确保 电脑答对了


    Arduino是否将接收到的
    Ok
    发送回?
    Serial.available()是的,我希望代码在while循环中等待,而只有2个字节,当有3个字节时就会返回(如“Ok\n”)。当你说清除缓冲区时,你的意思是刷新它吗?Arduino
    循环的体系结构()
    函数不符合该函数的定期调用。注意:该函数中的开括号数似乎不等于闭括号数。Arduino源代码是否编译无误?如果没有,则在
    ServoCo()中缺少最后一个闭括号。
    
    void loop() {
    
    static eState LoopState = STATE_START; // to store the current state
    static ePos ServoPos = FIRST_POS;  // to store the selected position
    
        eState NextState = LoopState;
    
        switch (LoopState) {
        case STATE_START:
            ServoPos = FIRST_POS;
            NextState = STATE_MOVE_POS;
            break;
        case STATE_MOVE_POS:
            NextState = STATE_SEND_CMD;
            break;
        case STATE_SEND_CMD:
            NextState = STATE_WAIT_ACK;
            break;
        case STATE_WAIT_ACK:
            // NextState = STATE_MOVE_POS;
            break;
        default:
            // when undefined state, restart
            NextState = STATE_START;
        }
        // define the state for the next loop
        LoopState = NextState;
    }
    
    switch (ServoPos) {
    case FIRST_POS:
        ServoCo(15); // go to 'Co' position
        break;
    case SECOND_POS:
        ServoCross(15); // go to 'Cross' position
        break;
    };
    NextState = STATE_SEND_CMD; // when reached, send serial message
    
    Serial.flush();   // clear the serial buffer
    if (ServoPos == FIRST_POS) {
        Serial.println("Co"); //send signal 'Co' to python
    }
    else {
        Serial.println("Cross"); //send signal 'Cross' to python
    }
    NextState = STATE_WAIT_ACK;
    
    if (Serial.available()) { // no state change while no acknowledge
        String Str = Serial.readStringUntil('\n');
        Serial.println(Str);
        if (Str == "OK") {
            // ack is OK, select the next position and continue
            ServoPos = (ServoPos == FIRST_POS)?(SECOND_POS):(FIRST_POS);
            NextState = STATE_MOVE_POS;
        }
        else {
            // ack is KO, restart from first position
            NextState = STATE_START;
        }
    }