gpt4 book ai didi

c# - 由c#程序控制的Arduino设备

转载 作者:太空宇宙 更新时间:2023-11-03 14:54:33 24 4
gpt4 key购买 nike

我正在做一个小项目 ( http://www.instructables.com/id/Digispark-Volume-Control/ ),它使用 digispark 和旋转编码器来控制媒体(音量、静音、暂停、下一个、上一个)。音量由旋转编码器的旋转控制,其他东西由按特定方式按下按钮控制:1 次为暂停,2 次为静音,短按上一首歌曲,长按下一首歌曲。

我在问我如何一起使用 c# 和 arduino 来动态控制这些东西(设置和更改我上面提到的这些事件的作用,如果我做的很远,可能会添加一些像使用宏编辑器的东西来自旋转编码器的模式来做东西)。宏编辑器的例子,比如想法:如果我短按 2 次,最多 200 毫秒,然后用旋转编码器向左转,锁定计算机。

我正在尝试完成像 griffin powermate(https://griffintechnology.com/us/powermate)这样的事情,有一个软件可以设置设备的功能以及设备跟随软件

这是我为设备获得的当前代码,它只有控制媒体的基本功能:

#include "TrinketHidCombo.h"

#define PIN_ENCODER_A 0
#define PIN_ENCODER_B 2
#define PIN_BUTTON 1
#define TRINKET_PINx PINB

static uint8_t enc_prev_pos = 0;
static uint8_t enc_flags = 0;

void setup()
{
// set pins as input with internal pull-up resistors enabled
pinMode(PIN_ENCODER_A, INPUT);
pinMode(PIN_ENCODER_B, INPUT);
pinMode(PIN_BUTTON, INPUT_PULLUP);
digitalWrite(PIN_ENCODER_A, HIGH);
digitalWrite(PIN_ENCODER_B, HIGH);
digitalWrite(PIN_BUTTON, HIGH);

TrinketHidCombo.begin(); // start the USB device engine and enumerate

// get an initial reading on the encoder pins
if (digitalRead(PIN_ENCODER_A) == LOW) {
enc_prev_pos |= (1 << 0);
}
if (digitalRead(PIN_ENCODER_B) == LOW) {
enc_prev_pos |= (1 << 1);
}
}

void loop()
{
int8_t enc_action = 0; // 1 or -1 if moved, sign is direction

// note: for better performance, the code will now use
// direct port access techniques
// http://www.arduino.cc/en/Reference/PortManipulation
uint8_t enc_cur_pos = 0;
// read in the encoder state first
if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
enc_cur_pos |= (1 << 0);
}
if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
enc_cur_pos |= (1 << 1);
}

// if any rotation at all
if (enc_cur_pos != enc_prev_pos)
{
if (enc_prev_pos == 0x00)
{
// this is the first edge
if (enc_cur_pos == 0x01) {
enc_flags |= (1 << 0);
}
else if (enc_cur_pos == 0x02) {
enc_flags |= (1 << 1);
}
}

if (enc_cur_pos == 0x03)
{
// this is when the encoder is in the middle of a "step"
enc_flags |= (1 << 4);
}
else if (enc_cur_pos == 0x00)
{
// this is the final edge
if (enc_prev_pos == 0x02) {
enc_flags |= (1 << 2);
}
else if (enc_prev_pos == 0x01) {
enc_flags |= (1 << 3);
}

// check the first and last edge
// or maybe one edge is missing, if missing then require the middle state
// this will reject bounces and false movements
if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
enc_action = 1;
}
else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
enc_action = 1;
}
else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
enc_action = -1;
}
else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
enc_action = -1;
}

enc_flags = 0; // reset for next time
}
}

// Get button event and act accordingly
int b = checkButton();
if (b == 1) clickEvent();
if (b == 2) doubleClickEvent();
if (b == 3) holdEvent();
if (b == 4) longHoldEvent();

enc_prev_pos = enc_cur_pos;

if (enc_action > 0) {
TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
}
else if (enc_action < 0) {
TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
}
else {
TrinketHidCombo.poll(); // do nothing, check if USB needs anything done
}
}

//=================================================
// Events to trigger

void clickEvent() {
TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE);
}
void doubleClickEvent() {
TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
}
void holdEvent() {
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_PREV_TRACK);
}
void longHoldEvent() {
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK);
}

int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 500; // max ms between clicks for a double click event
int holdTime = 1000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 1500; // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH; // value read from button
boolean buttonLast = HIGH; // buffered value of the button's previous state
boolean DCwaiting = false; // whether we're waiting for a double click (down)
boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true; // whether it's OK to do a single click
long downTime = -1; // time the button was pressed down
long upTime = -1; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false; // when held, whether to wait for the up event
boolean holdEventPast = false; // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {
int event = 0;
buttonVal = digitalRead(PIN_BUTTON);
// Button pressed down
if (buttonVal == HIGH && buttonLast == LOW && (millis() - upTime) > debounce)
{
downTime = millis();
ignoreUp = false;
waitForUp = false;
singleOK = true;
holdEventPast = false;
longHoldEventPast = false;
if ((millis() - upTime) < DCgap && DConUp == false && DCwaiting == true) DConUp = true;
else DConUp = false;
DCwaiting = false;
}
// Button released
// DOUBLE CLICK
else if (buttonVal == HIGH && buttonLast == HIGH && (millis() - downTime) > debounce)
{
if (not ignoreUp)
{
upTime = millis();
if (DConUp == false) DCwaiting = true;
else
{
event = 2;
DConUp = false;
DCwaiting = false;
singleOK = false;
}
}
}
// Test for normal click event: DCgap expired
if ( buttonVal == LOW && (millis() - upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
{
event = 1;
DCwaiting = false;
}
// Test for hold
if (buttonVal == HIGH && (millis() - downTime) >= holdTime) {
// Trigger "normal" hold
if (not holdEventPast)
{
event = 3;
waitForUp = true;
ignoreUp = true;
DConUp = false;
DCwaiting = false;
//downTime = millis();
holdEventPast = true;
}
// Trigger "long" hold
if ((millis() - downTime) >= longHoldTime)
{
if (not longHoldEventPast)
{
event = 4;
longHoldEventPast = true;
}
}
}
buttonLast = buttonVal;
return event;
}

最佳答案

由于您无法在 Arduino 本身上运行 C# 代码,因此代码需要在 PC(或 Raspberry Pi 或使用 .NET Core 的类似设备)上运行。

所以这意味着您需要一种在两者之间进行通信的方法。您的选择是:

  1. 通过串口(通过 USB 串口)来回发送消息(最简单,因为您可能已经在使用串口对 Arduino 进行编程)。
  2. 使用 WIFI 或以太网并创建一个 WebAPI 端点,Arduino 调用该端点来传递消息并获得结果。
  3. 使用其他一些通信机制,例如蓝牙。

或者,如果您有像 Trinket 这样的设备,它只支持通过 USB 进行键盘模拟,您需要选择一些未使用的键码来发送,然后让您的应用程序挂接到全局事件中以处理它们(参见 https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/ ) - 当然,除非您的应用程序在前台,在这种情况下,您可以在设备发送输入时从键盘读取输入。

关于c# - 由c#程序控制的Arduino设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50262802/

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