微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Teensy 和 C++ 程序通信问题

如何解决Teensy 和 C++ 程序通信问题

我有一个 WS2812 灯带,我试图通过一个 Teensy 4.0 通过 C++ 程序进行控制(teensy 最终会控制更多,并且需要将消息发送回 PC 以处理其中一些事情,但这就是重点我在)。

如果我通过 teensyduino 使用串行监视器,我的命令效果很好,但是,当我尝试将 Teensy 链接到我的程序时,它会连接,但只有一条消息通过/执行任何操作,然后它停止接收/发送消息,但并没有完全断开连接。

硬件设置是 PC→Teensy4.0→LightStrip(还有一些其他的东西,比如灯带的电源、升压逻辑板和电阻器)。我觉得我在某处遗漏了一个简单的步骤。

我的青少年代码

#include <FastLED.h>

#define LED_PIN     0
#define NUM_LEDs    80 
CRGB stripLEDs[NUM_LEDs];

String computerMessage = "";
char computerCommand = '\0';

enum LEDColor {
  RED,ORANGE,YELLOW,GREEN,CYAN,BLUE,PURPLE,magenta,WHITE,OFF
};

LEDColor userColor1 = WHITE;
LEDColor userColor2 = OFF;
LEDColor partyFirstLED = RED;

bool twoColors = false;
bool isWideColors = false;
bool setStrip = true;
char colorChar = '\0';

void setup() {
  // put your setup code here,to run once:
Serial.begin(115200);

FastLED.addLeds<WS2812,LED_PIN,GRB>(stripLEDs,NUM_LEDs);

}

void SetLEDColor(int lednumber,LEDColor colorToSet){

    switch (colorToSet){
    case RED:
      stripLEDs[lednumber] = CRGB(255,0);
      break;
    case ORANGE:
      stripLEDs[lednumber] = CRGB(255,50,0);
      break;
    case YELLOW:
      stripLEDs[lednumber] = CRGB(200,100,0);
      break;
    case GREEN:
      stripLEDs[lednumber] = CRGB(0,255,0);
      break;
    case CYAN:
      stripLEDs[lednumber] = CRGB(0,200,150);
      break;
    case BLUE:
      stripLEDs[lednumber] = CRGB(0,255);
      break;
    case magenta:
      stripLEDs[lednumber] = CRGB(255,80);
      break;
    case PURPLE:
      stripLEDs[lednumber] = CRGB(200,255);
      break;
    case WHITE:
      stripLEDs[lednumber] = CRGB(100,100);
      break;
    case OFF:
    default:
      stripLEDs[lednumber] = CRGB(0,0);
      break;
  }
  
}

void loop() {
  // put your main code here,to run repeatedly:
  
  if(Serial.available() != 0)
  {
    computerMessage = Serial.readStringUntil('\n');
  }

  computerCommand = computerMessage.charat(0);

  if(computerMessage != "")
  {
    computerCommand = computerMessage.charat(0);
    switch (computerCommand){
      case 'c':
        if(computerMessage.length() > 1)
        {
          colorChar = computerMessage.charat(1);
        }
        switch(colorChar){
          case 'R':
            userColor1 = RED;
            Serial.println("Color 1 is red");
            break;
          case 'A':
            userColor1 = ORANGE;
            Serial.println("Color 1 is orange");
            break;
          case 'Y':
            userColor1 = YELLOW;
            Serial.println("Color 1 is yellow");
            break;
          case 'G':
            userColor1 = GREEN;
            Serial.println("Color 1 is green");
            break;
          case 'C':
            userColor1 = CYAN;
            Serial.println("Color 1 is cyan");
            break;
          case 'B':
            userColor1 = BLUE;
            Serial.println("Color 1 is blue");
            break;
          case 'P':
            userColor1 = PURPLE;
            Serial.println("Color 1 is purple");
            break;
          case 'M':
            userColor1 = magenta;
            Serial.println("Color 1 is magenta");
            break;
          case 'W':
            userColor1 = WHITE;
            Serial.println("Color 1 is white");
            break;
          case 'F':
          default:
            userColor1 = OFF;
            Serial.println("Color 1 is off");
            break;
        }
        setStrip = true;
        break;
      case 'C':
        if(computerMessage.length() > 1)
        {
          colorChar = computerMessage.charat(1);
        }
        switch(colorChar){
          case 'R':
            userColor2 = RED;
            Serial.println("Color 2 is red");
            break;
          case 'A':
            userColor2 = ORANGE;
            Serial.println("Color 2 is orange");
            break;
          case 'Y':
            userColor2 = YELLOW;
            Serial.println("Color 2 is yellow");
            break;
          case 'G':
            userColor2 = GREEN;
            Serial.println("Color 2 is green");
            break;
          case 'C':
            userColor2 = CYAN;
            Serial.println("Color 2 is cyan");
            break;
          case 'B':
            userColor2 = BLUE;
            Serial.println("Color 2 is blue");
            break;
          case 'P':
            userColor2 = PURPLE;
            Serial.println("Color 2 is purple");
            break;
          case 'M':
            userColor2 = magenta;
            Serial.println("Color 2 is magenta");
            break;
          case 'W':
            userColor2 = WHITE;
            Serial.println("Color 2 is white");
            break;
          case 'F':
          default:
            userColor2 = OFF;
            Serial.println("Color 2 is off");
            break;
        }
        setStrip = true;
        break;
      case 'n':
        isWideColors = false;
        setStrip = true;
        break;
      case 'o':
        twoColors = false;
        setStrip = true;
        break;
      case 't':
        twoColors = true;
        setStrip = true;
        break;
      case 'w':
        isWideColors = true;
        setStrip = true;
        break;
      default:
        break;
    }
    computerCommand = '\0';
    computerMessage = "";
  }

  

  if(setStrip)
  {
    if(twoColors)
    {
      if(isWideColors)
      {
        for(int i = 0; i <= NUM_LEDs; i++)
        {
          if(i % 10 == 0)
          {
            SetLEDColor(i,userColor1);
          }
          else if((i-1) % 10 == 0 )
          {
            SetLEDColor(i,userColor1);
          }
          else if((i-2) % 10 == 0 )
          {
            SetLEDColor(i,userColor1);
          }
          else if((i-3) % 10 == 0 )
          {
            SetLEDColor(i,userColor1);
          }
          else if((i-4) % 10 == 0 )
          {
            SetLEDColor(i,userColor1);
          }
          else
          {
            SetLEDColor(i,userColor2);
          }
        }
      }
      else
      {
        for(int i = 0; i <= NUM_LEDs; i++)
        {
          if(i % 2 == 0)
          {
            SetLEDColor(i,userColor2);
          }
        }
      }
      FastLED.show();
      setStrip = false;
    }
    else
    {
      for(int i = 0; i <= NUM_LEDs; i++)
      {
        SetLEDColor(i,userColor1);
      }
      FastLED.show();
      setStrip = false;
    }
  }

}

我的主要(PC代码):

    #include "TeensyMessageHandler.h"
    
    std::string UserCommand;
    
    std::thread* pGetUserCommandsThread;
    
    void CloseUserCommandsThread()
    {
        if (pGetUserCommandsThread != nullptr)
        {
            pGetUserCommandsThread->join();
            delete pGetUserCommandsThread;
            pGetUserCommandsThread = nullptr;
        }
    }
    
    void GetUserCommands()
    {
        TeensyMessageHandler* pTeensyMessageHandler = TeensyMessageHandler::GetInstance();
        while (true)
        {
            std::cin >> UserCommand;
            pTeensyMessageHandler->GiveTeensyCommand(UserCommand);
        }
    }
    
    int main()
    {
    TeensyMessageHandler* pTeensyMessageHandler = TeensyMessageHandler::GetInstance();
    Sleep(1000);

    pGetUserCommandsThread = new std::thread(&GetUserCommands);

    while (true)
    {
        pTeensyMessageHandler->UpdateTeensyMessageHandler();

        Sleep(200);
    }

    CloseUserCommandsThread();

    return 0;
}

我的连接处理程序代码(PC): (标题):

#pragma once


#define TEENSY_WAIT_TIME 200
#define MAX_DATA_LENGTH 255

#include <Windows.h>

class TeensySerialPort
{
public:
    explicit TeensySerialPort(const char* portName);
    ~TeensySerialPort();

    int readSerialPort(const char* buffer,unsigned int buf_size);
    bool writeSerialPort(const char* buffer,unsigned int buf_size);
    bool isConnected();
    void closeSerial();

private:
    HANDLE handler;
    bool connected;
    COMSTAT status;
    DWORD errors;
};

我的连接处理程序代码(PC): (cpp):

#include "TeensySerialPort.h"
#include <iostream>

TeensySerialPort::TeensySerialPort(const char* portName)
{
    this->connected = false;

    this->handler = CreateFileA(static_cast<LPCSTR>(portName),GENERIC_READ | GENERIC_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_norMAL,NULL);

    if (this->handler == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            std::cout << "Teensy Serial Port Error: Handle not attached. Port Unavailable. Port Name: " << portName << std::endl;
        }
        else
        {
            std::cout << "Teensy Serial Port Error.  Port Name: " << portName << std::endl;
        }

    }
    else
    {
        DCB dcbSerialParameters = { 0 };

        if (!GetCommState(this->handler,&dcbSerialParameters))
        {
            std::cout << "Failed to get current serial parameters. Port Name: " << portName << std::endl;
        }
        else
        {
            dcbSerialParameters.Baudrate = CBR_115200;
            dcbSerialParameters.ByteSize = 8;
            dcbSerialParameters.StopBits = OnesTOPBIT;
            dcbSerialParameters.Parity = nopARITY;
            dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;

            if (!SetCommState(handler,&dcbSerialParameters))
            {
                std::cout << "Could not set serial port parameters.  Port Name: " << portName << std::endl;
            }
            else
            {
                this->connected = true;
                PurgeComm(this->handler,PURGE_RXCLEAR | PURGE_TXCLEAR);
                Sleep(TEENSY_WAIT_TIME);
            }
        }
    }
}

TeensySerialPort::~TeensySerialPort()
{
    if (this->connected)
    {
        this->connected = false;
        CloseHandle(this->handler);
    }
}

int TeensySerialPort::readSerialPort(const char* buffer,unsigned int buf_size)
{
    DWORD bytesRead{};
    unsigned int toRead = 0;

    ClearCommError(this->handler,&this->errors,&this->status);

    if (this->status.cbInQue > buf_size)
    {
        toRead = buf_size;
    }
    else
    {
        toRead = this->status.cbInQue;
    }

    memset((void*)buffer,buf_size);

    if (ReadFile(this->handler,(void*)buffer,toRead,&bytesRead,NULL))
    {
        return bytesRead;
    }

    return 0;
}

// sending provided buffer to serial port;
// returns true if succeed,false if Failed
bool TeensySerialPort::writeSerialPort(const char* buffer,unsigned int buf_size)
{
    DWORD bytesSend;

    if (!WriteFile(this->handler,buf_size,&bytesSend,0))
    {
        ClearCommError(this->handler,&this->status);
            return false;
    }
    return true;
}

//checking if serial port is connected
bool TeensySerialPort::isConnected()
{
    if (this != nullptr)
    {
        if (!ClearCommError(this->handler,&this->status))
        {
            this->connected = false;
        }

        return this->connected;
    }
    else
    {
        return false;
    }
}

void TeensySerialPort::closeSerial()
{
    CloseHandle(this->handler);
}

和消息处理程序(PC):标题

#pragma once

#include <Windows.h>
#include <iostream>
#include <string>
#include <thread>
#include "TeensySerialPort.h"

class TeensyMessageHandler
{
public:
    TeensyMessageHandler();
    ~TeensyMessageHandler();

    static TeensyMessageHandler* GetInstance();
    static bool DestroyInstance();

    void Init();

    void UpdateTeensyMessageHandler();

    void GiveTeensyCommand(std::string deviceCommand);

    
private:

    static TeensyMessageHandler* m_pTeensyMessageHandler;

    std::string m_szTeensyMessage;

    void SendMessagetoTeensy(std::string szCommand);
    std::string GetTeensyMessage();

    TeensySerialPort* Teensy = new TeensySerialPort("\\\\.\\COM7");

    char output[MAX_DATA_LENGTH];
    char incoming[MAX_DATA_LENGTH];

    std::thread* m_pHandleTeensyThread;
    void DoHandleTeensyThread();

    void CloseTeensyThread();

    std::string m_szTeensyPortName;
    bool m_bHandleTeensyThreadActive;
    bool m_bPauseNeeded;

};

(cpp):

#include "TeensyMessageHandler.h"

#define SEND_DATA_LENGTH        255
#define RECEIVE_DATA_LENGTH     255
#define NL_TEENSY_PORT_NAME     "\\\\.\\COM"

TeensyMessageHandler* TeensyMessageHandler::m_pTeensyMessageHandler;

TeensyMessageHandler::TeensyMessageHandler() :
    m_szTeensyMessage(""),m_szTeensyPortName(NL_TEENSY_PORT_NAME + 7),incoming(""),m_bHandleTeensyThreadActive(false),m_bPauseNeeded(false)
{
}

TeensyMessageHandler::~TeensyMessageHandler()
{
    if (Teensy != nullptr)
    {
        Teensy->closeSerial();
    }
    CloseTeensyThread();
}

void TeensyMessageHandler::Init()
{
    m_pHandleTeensyThread = new std::thread(&TeensyMessageHandler::DoHandleTeensyThread,this);
}

void TeensyMessageHandler::DoHandleTeensyThread()
{
    m_bHandleTeensyThreadActive = true;

    int i = 6;
    while (!Teensy->isConnected())
    {
        std::string TeensyPortName = m_szTeensyPortName;
        std::cout << "Could Not Connect to Teensy.  Port: " << TeensyPortName << std::endl;
        delete Teensy;
        m_szTeensyPortName = NL_TEENSY_PORT_NAME + std::to_string(i);

        Teensy = new TeensySerialPort(m_szTeensyPortName.c_str());
        i++;
        if (i >= 20)
        {
            i = 1;
        }

    }

    if (m_bPauseNeeded)
    {
        Sleep(1000);
        m_bPauseNeeded = false;
    }

    std::string TeensyPortName = m_szTeensyPortName;
    std::cout << "Connected to Teensy.  Port: " << TeensyPortName << std::endl;

    char receivedMessage[RECEIVE_DATA_LENGTH];
    std::string receivedMessageAsstring = "";

    while (Teensy->isConnected())
    {
        if (Teensy != nullptr)
        {
            Teensy->readSerialPort(receivedMessage,RECEIVE_DATA_LENGTH);
            receivedMessageAsstring = receivedMessage;
            if (receivedMessageAsstring != "")
            {
                std::cout << receivedMessageAsstring << std::endl;
            }
            
        }
    }
    m_bHandleTeensyThreadActive = false;
}

void TeensyMessageHandler::UpdateTeensyMessageHandler()
{
    if (m_bHandleTeensyThreadActive == false)
    {
        CloseTeensyThread();
        m_pHandleTeensyThread = new std::thread(&TeensyMessageHandler::DoHandleTeensyThread,this);
    }
}

void TeensyMessageHandler::CloseTeensyThread()
{
    if (m_pHandleTeensyThread != nullptr)
    {
        m_pHandleTeensyThread->join();
        delete m_pHandleTeensyThread;
        m_pHandleTeensyThread = nullptr;
    }
}

void TeensyMessageHandler::GiveTeensyCommand(std::string Message)
{
    if (Message == "Red")
    {
        SendMessagetoTeensy("cR");
    }
    else if (Message == "Orange")
    {
        SendMessagetoTeensy("cO");
    }
    else if (Message == "Yellow")
    {
        SendMessagetoTeensy("cY");
    }
    else if (Message == "Green")
    {
        SendMessagetoTeensy("cG");
    }
    else if (Message == "Cyan")
    {
        SendMessagetoTeensy("cC");
    }
    else if (Message == "Blue")
    {
        SendMessagetoTeensy("cB");
    }
    else if (Message == "Purple")
    {
        SendMessagetoTeensy("cP");
    }
    else if (Message == "magenta")
    {
        SendMessagetoTeensy("cM");
    }
    else if (Message == "White")
    {
        SendMessagetoTeensy("cW");
    }
    else if (Message == "Off")
    {
        SendMessagetoTeensy("cF");
    }
    else if (Message == "Red2")
    {
        SendMessagetoTeensy("CR");
    }
    else if (Message == "Orange2")
    {
        SendMessagetoTeensy("CO");
    }
    else if (Message == "Yellow2")
    {
        SendMessagetoTeensy("CY");
    }
    else if (Message == "Green2")
    {
        SendMessagetoTeensy("CG");
    }
    else if (Message == "Cyan2")
    {
        SendMessagetoTeensy("CC");
    }
    else if (Message == "Blue2")
    {
        SendMessagetoTeensy("CB");
    }
    else if (Message == "Purple2")
    {
        SendMessagetoTeensy("CP");
    }
    else if (Message == "magenta2")
    {
        SendMessagetoTeensy("CM");
    }
    else if (Message == "White2")
    {
        SendMessagetoTeensy("CW");
    }
    else if (Message == "Off2")
    {
        SendMessagetoTeensy("CF");
    }
    else if (Message == "TwoColors")
    {
        SendMessagetoTeensy("t");
    }
    else if (Message == "OneColor")
    {
        SendMessagetoTeensy("o");
    }
    else if (Message == "Wide")
    {
        SendMessagetoTeensy("w");
    }
    else if (Message == "Narrow")
    {
        SendMessagetoTeensy("n");
    }
}

void TeensyMessageHandler::SendMessagetoTeensy(std::string Command)
{
    const char* sendString = Command.c_str();

    if (Teensy->isConnected())
    {
        bool hasWritten = false;
        hasWritten = Teensy->writeSerialPort(sendString,SEND_DATA_LENGTH);

        if (hasWritten)
        {
            std::cout << "Sent Teensy Message: " << Command << std::endl;
        }
        else
        {
            std::cout << "Failed to send Teensy message: " << Command << std::endl;
        }
    }
}

std::string TeensyMessageHandler::GetTeensyMessage()
{
    char receivedString[RECEIVE_DATA_LENGTH];

    if (Teensy->isConnected())
    {
        int hasRead = Teensy->readSerialPort(receivedString,RECEIVE_DATA_LENGTH);
    }

    return std::string(receivedString);
}

TeensyMessageHandler* TeensyMessageHandler::GetInstance()
{
    if (!m_pTeensyMessageHandler)
    {
        m_pTeensyMessageHandler = new TeensyMessageHandler();
        m_pTeensyMessageHandler->Init();
    }
    return m_pTeensyMessageHandler;
}

bool TeensyMessageHandler::DestroyInstance()
{
    bool bSuccess = false;
    if (m_pTeensyMessageHandler)
    {
        delete m_pTeensyMessageHandler;
        bSuccess = true;
    }
    return bSuccess;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。