/****************************/ /* PWM出力のテスト */ /****************************/ // USB(Serial)で通信 // Serial1でPWM値の変化を出力 // PWM周波数は500Hz, 8bit分解能 // タイトル const char ttl_msg[] = "# Pico PWM Test #4 (2023-02-21)"; const char *inp_msg[] = { // inp_modeで区分して出力 "# PWM Port >", // 0:PWMポート番号入力 "# PWM Range (255,256...) >", // 1:PWM レンジ "# PWM Data (0...255) >", // 2:PWMデータ入力 }; // LED点滅 #define LED_PORT 25 // 1出力でLEDオン /****************************/ /* 送受データ */ /****************************/ /***** 送信データ *****/ char tx_str[64]; // 送信文字列 /***** シリアル1行入力 *****/ #define RXBF_SIZ 32 // 文字バッファ文字数 char rx_bff[RXBF_SIZ+1]; // 受信文字バッファ (+null) byte f_rxok; // 受信データありフラグ /***** シリアル1行受信 *****/ // CRでターミネート f_rxokを1に // エコーバックありで // なし→BSで1文字戻す void rxbff(void) { static byte cnt = 0; // 受信文字数 char c; if(Serial.available()){ // 受信データあり if(f_rxok == 0){ // 前データ受信処理した c = Serial.read(); // 1文字読み出し if(c == '\r'){ // CR? rx_bff[cnt] = '\0'; // nullを最後に Serial.println(); // 改行 f_rxok = 1; // 受信成功 cnt = 0; // 最初から } else if(c == '\x08'){ // BS? if(cnt > 0){ cnt--; // 1文字戻す Serial.print("\b \b"); // BS,space,BS } } else{ // 文字 if((cnt < RXBF_SIZ) && // バッファサイズ内 (isprint(c))){ // 表示可能文字0x20~0x7E Serial.write(c); // エコーバック rx_bff[cnt] = c; // バッファに入れる cnt++; // 1文字進める } } } } } /****************************/ /* PWM出力 */ /****************************/ #include "pwm.h" // PWM処理に必要 // PWMデータ int pwm_port; // PWMポート番号 int pwm_range = 256; // PWM レンジ 初期値は256 int pwm_data; // PWM設定値データ /***** PWM出力 *****/ // pinに出力 valがPWM H区間 最大がrange // val=0ならL出力 val=rangeならH出力 // ピコのクロックは125MHz // val,rangeを10倍して処理 // set_clkdivは256.0未満 m・n/16で分周 // set_wrap,set_chan_levelはuint16_tなので65535がmax void pwmWrite(pin_size_t pin, int val, int range) { uint sn; // slice number gpio_set_function(pwm_port, GPIO_FUNC_PWM); // ポートはPWM出力で sn = pwm_gpio_to_slice_num(pwm_port); // スライス番号を得る pwm_set_clkdiv(sn, 97.66); // 1.28MHzに pwm_set_wrap(sn, (10 * range) - 1); // 256で500Hz pwm_set_chan_level(sn, (pwm_port & 1), 10 * val); // ch-A,ch-B pwm_set_enabled(sn, true); // PWMスタート } /*********************************/ /* 制御実行処理 */ /*********************************/ // 制御用データ int inp_mode; // 入力モード // 0 : PWMポート番号 // 1 : PWM bit数 // 2 : PWMデータ int tm_100ms; // 100ms ダウンカウントタイマー /***** 制御実行区分 *****/ byte j_exc; // 実行区分 #define J_DATAIN 1 // データ入力 #define J_SCAN 3 // PWMスキャン /***** スタンバイ *****/ // 最初のCR入力を待ってタイトル表示 void jstby(void) { if(f_rxok){ // CR入力待ち f_rxok = 0; Serial.println(); // 改行 Serial.println(ttl_msg); // タイトル出力 j_exc++; // next exc } } /***** 数値入力 入力項目表示 *****/ // inp_modeで入力対象を変更 void jdatain(void) { Serial.print(inp_msg[inp_mode]); // 入力項目 j_exc++; // next exc } /***** 数値入力 データ入力処理 *****/ // PWMポート番号あるいはPWMデータ void jdatain1(void) { int d; int n; if(f_rxok){ // CR入力待ち f_rxok = 0; n = strlen(rx_bff); // 文字数 d = atoi(rx_bff); // 数値に変換 switch(inp_mode){ case 0: // PWMポート番号入力 if(n){ // 入力文字あり pwm_port = d; // ポート番号を設定 inp_mode++; // 次はレンジ } j_exc = J_DATAIN; break; case 1: // PWMレンジを入力 if(n){ // 入力文字あり pwm_range = d; // 256,1024 最大値を設定 } // 入力なくても pwmWrite(pwm_port, pwm_range/2, pwm_range); // PWM duty 50%出力 inp_mode++; // データ入力に j_exc = J_DATAIN; break; case 2: // PWMデータ入力 if(n == 0){ // 入力文字なし inp_mode = 0; // PWMポート入力に j_exc = J_DATAIN; // 戻してもう一度 } else{ // 入力あり pwm_data = d; if(pwm_data >= 0){ // 0~プラスならPWM値セット pwmWrite(pwm_port, pwm_data, pwm_range); // PWM出力 sprintf(tx_str, "PWM %2d %4d/%4d", pwm_port, pwm_data, pwm_range); Serial.println(tx_str); j_exc = J_DATAIN; // 繰り返し } else{ // マイナスなら連続可変へ Serial.println("Scan."); pwm_data = 1; // 1~pwm_range-1まで j_exc = J_SCAN; // 出力開始 } } break; } } } /***** PWM値連続可変 *****/ // 2秒サイクルで出力 void jscan(void) { pwmWrite(pwm_port, pwm_data, pwm_range); // PWM出力 sprintf(tx_str, "%4d", pwm_data); Serial.println(tx_str); // USB Serial1.println(tx_str); // TX1 tm_100ms = 20; // 2秒タイマーセット j_exc++; // next exc } /***** PWM値連続可変 #1 *****/ // タイムアップで次データへ void jscan1(void) { byte bk = 0; if(f_rxok){ // CR入力で中断 f_rxok = 0; Serial.println("Break."); bk = 1; } if(tm_100ms == 0){ // タイムアップした pwm_data++; // PWM値を+1 if(pwm_data >= pwm_range){ // 1~255を出力完了? Serial.println("Finish."); bk = 1; // おわり } else{ // 時間待ち j_exc = J_SCAN; // PWM出力続行 } } if(bk){ // おわり inp_mode = 0; // PWMポート番号入力に j_exc = J_DATAIN; // 戻してもう一度 } } /********************************/ /* 制御実行テーブル */ /********************************/ /***** 制御実行 *****/ void (*jexc[])(void)={ jstby, // 0:スタンバイ jdatain, // * 1:データ入力 jdatain1, // 2 jscan, // * 3:連続PWM出力 jscan1, // 4 }; /****************************/ /* SETUP */ /****************************/ /***** SETUP *****/ void setup() { Serial.begin(9600); // USB TX,RX Serial1.begin(9600); // TX1 pinMode(LED_PORT, OUTPUT); // LED } /****************************/ /* LOOP */ /****************************/ /***** LOOP *****/ void loop() { byte f_led = 0; // LED点滅用 uint32_t t0, t1; // タイマー t0 = millis(); while(1){ t1 = millis(); if((t1 - t0) >= 100){ // 0.1秒経過? t0 = t1; f_led ^= 1; // LED トグル gpio_put(LED_PORT, f_led); // LED出力 if(tm_100ms) tm_100ms--; // 100ms ダウンカウントタイマー } rxbff(); // 1行受信処理 jexc[j_exc](); // 制御実行区分で } } /*==== end of "pwm_serial_in4.ino" ====*/