Instantly share code, notes, and snippets.
Last active
November 24, 2021 14:30
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save KeitetsuWorks/983e5bcb58e60b28b9ed47eceb684191 to your computer and use it in GitHub Desktop.
Arduino: ボタンスイッチでサーボモータの角度を切り替える
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file servo_button.ino | |
* @brief Servo Motor Controller | |
* @author Keitetsu | |
* @date 2021/09/29 | |
* @copyright Copyright (c) 2021 Keitetsu | |
* @par License | |
* This software is released under the MIT License. | |
*/ | |
#include <Servo.h> | |
#define SERVO_NUM 1 /**< サーボモータの数 */ | |
#define BTN_NUM 1 /**< ボタンスイッチの数 */ | |
#define BTN_COUNT_THRESH 2 /**< ボタンスイッチの状態の確定閾値 */ | |
#define SERIAL_TX_BUF_SIZE 14 /**< シリアル通信の送信バッファのサイズ */ | |
#define INTERVAL_TIME 20 /**< 周期実行の間隔 */ | |
/** | |
* @struct button_st | |
* @brief ボタンスイッチ管理構造体 | |
* | |
* @typedef BUTTON_T | |
* @brief ボタンスイッチ管理構造体 | |
*/ | |
typedef struct button_st | |
{ | |
uint8_t pin; /**< 接続ピン */ | |
uint8_t last_val; /**< 前回の入力値 */ | |
uint8_t count; /**< 最後に入力値が変化してからのカウント値 */ | |
uint8_t state; /**< 状態 */ | |
} BUTTON_T; | |
BUTTON_T btns[BTN_NUM]; /**< ボタンスイッチ */ | |
unsigned long prev_time; /**< 周期実行の前回実行時刻 */ | |
unsigned long interval_time; /**< 周期実行の間隔 */ | |
/** | |
* @brief サーボモータ | |
*/ | |
Servo servos[SERVO_NUM]; | |
/** | |
* @brief サーボモータの位置 | |
*/ | |
int servos_pos[SERVO_NUM]; | |
/** | |
* @brief ボタンスイッチ管理構造体を初期化する | |
* @param[in,out] btn ボタンスイッチ管理構造体のポインタ | |
* @param[in] pin ボタンスイッチの接続ピン | |
*/ | |
void initBtn(BUTTON_T *btn, uint8_t pin) | |
{ | |
btn->pin = pin; | |
pinMode(btn->pin, INPUT); | |
btn->last_val = digitalRead(btn->pin); | |
btn->count = 0; | |
btn->state = btn->last_val; | |
return; | |
} | |
/** | |
* @brief ボタンスイッチの状態を更新する (周期実行) | |
* @param[in,out] btn ボタンスイッチ管理構造体のポインタ | |
* @retval true ボタンスイッチの状態に変化あり | |
* @retval false ボタンスイッチの状態に変化なし | |
*/ | |
uint8_t updateBtnState(BUTTON_T *btn) | |
{ | |
uint8_t is_changed; | |
uint8_t btn_val; | |
is_changed = false; | |
btn_val = digitalRead(btn->pin); | |
if (btn_val != btn->last_val) | |
{ | |
// 入力値が変化した場合はカウント値を0にする | |
btn->last_val = btn_val; | |
btn->count = 0; | |
} | |
else | |
{ | |
if (btn->count < 255) | |
{ | |
// 入力値が変化していない場合はカウントアップ | |
btn->count++; | |
} | |
if (btn->count == BTN_COUNT_THRESH) | |
{ | |
// 最後に入力値が変化してからのカウント値が | |
// BTN_COUNT_THRESHに達した場合,ボタンスイッチの状態を確定する | |
is_changed = true; | |
btn->state = btn_val; | |
} | |
} | |
return is_changed; | |
} | |
/** | |
* @brief ボタンスイッチの状態を取得する | |
* @param[in] btn ボタンスイッチ管理構造体のポインタ | |
* @return ボタンスイッチの状態 | |
*/ | |
uint8_t getBtnState(BUTTON_T *btn) | |
{ | |
return btn->state; | |
} | |
/** | |
* @brief サーボモータの位置を更新する | |
*/ | |
void update_servos_pos() | |
{ | |
uint8_t i; | |
uint8_t btn_is_changed; | |
uint8_t btn_state; | |
char tx_buf[SERIAL_TX_BUF_SIZE]; | |
// ボタンスイッチの状態に変化がある場合は, | |
// サーボモータの位置を変更し,サーボモータの位置をシリアル通信で送信する | |
for (i = 0; i < BTN_NUM; i++) | |
{ | |
btn_is_changed = updateBtnState(&btns[i]); | |
btn_state = getBtnState(&btns[i]); | |
if (btn_is_changed && (btn_state == LOW)) | |
{ | |
servos_pos[i] = (servos_pos[i] != 0) ? 0 : 180; | |
servos[i].write(servos_pos[i]); | |
sprintf(tx_buf, "Servo[%1u]: %3u\n", i, servos_pos[i]); | |
Serial.print(tx_buf); | |
} | |
} | |
return; | |
} | |
/** | |
* @brief セットアップ関数 | |
*/ | |
void setup() | |
{ | |
uint8_t i; | |
uint8_t btns_pin[BTN_NUM] = {2}; | |
uint8_t servos_pin[SERVO_NUM] = {11}; | |
// ボタンスイッチの初期化 | |
for (i = 0; i < BTN_NUM; i++) | |
{ | |
initBtn(&btns[i], btns_pin[i]); | |
} | |
// 各サーボモータの初期化 | |
for (i = 0; i < SERVO_NUM; i++) | |
{ | |
// 引数はピン番号,最小パルス幅,最大パルス幅 | |
// パルス幅はサーボモータに合わせて調整する | |
servos[i].attach(servos_pin[i], 544, 2080); | |
servos_pos[i] = 0; | |
servos[i].write(servos_pos[i]); | |
} | |
// シリアル通信の初期化 | |
Serial.begin(9600); | |
// 周期実行の初期化 | |
prev_time = 0; | |
interval_time = INTERVAL_TIME; | |
} | |
/** | |
* @brief ループ関数 | |
*/ | |
void loop() | |
{ | |
unsigned long curr_time; | |
// 現在時刻を取得する | |
curr_time = millis(); | |
// 周期実行 | |
if ((curr_time - prev_time) >= interval_time) | |
{ | |
prev_time += interval_time; | |
update_servos_pos(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment