jonajiro が 2022年08月29日20時40分49秒 に編集
コメント無し
本文の変更
# はじめに SpresenseのPWM分解能について調査したので報告。 公式のSpresense Arduino IDEの開発ガイドではPWM分解能が256の例しか示されていない。 一方で下記URLではSpresense SDKのAPIをArduinoで叩けばいけるよ的なこと書いていたが具体的なプログラムが示されていなかったのでトライした。 [arduino-ideでpwm出力を15bitで扱う方法](https://ja.stackoverflow.com/questions/65475/arduino-ide%E3%81%A7pwm%E5%87%BA%E5%8A%9B%E3%82%9215bit%E3%81%A7%E6%89%B1%E3%81%86%E6%96%B9%E6%B3%95) また、Spresense SDKの下記URLのexampleを参考にした。 [https://github.com/jodersky/nuttx/blob/master/apps/examples/pwm/pwm_main.c](https://github.com/jodersky/nuttx/blob/master/apps/examples/pwm/pwm_main.c) 上記ソースコードはSpresense SDK をダウンロードすれば examples の中にマージされるのでそっち確認してもいいかも。 以下にPWMを動かした様子を示す。 @[twitter](https://twitter.com/k218675554/status/1563903011730395136) # プログラム ■ void pwm_init(int freq, float duty) PWMの初期化。※なくても動くけどSDKのexampleに記載があった。 1. freq:初期周波数指定。 最大は2kHzまでしか確認してないがスペック上6.5MHzは出るらしい。 1. duty:初期デュティ比指定 0~1をfloatで入力。0%なら0、50%なら0.5、100%なら1みたいな感じ。 ■ void pwm_output(int pin_num, int freq, float duty) PWMのポート、周波数、デュティ比の指示 1. pin_num:出力ポート指定 pin_numには0~3を入力する。拡張ボードのピン番号との対応は下記の通りだった。 pin_num 0:D6 pin_num 1:D5 pin_num 2:D3 pin_num 3:D9 1. freq:周波数指定。 最大は2kHzまでしか確認してないがスペック上6.5MHzは出るらしい。 1. duty:デュティ比指定 0~1をfloatで入力。0%なら0、50%なら0.5、100%なら1みたいな感じ。 ```arduino:pwm_test.ino
#include <nuttx/config.h> #include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <debug.h> #include <string.h>
#include <nuttx/timers/pwm.h> struct pwm_state_s { bool initialized; FAR char *devpath; uint8_t duty; uint32_t freq; }; static struct pwm_state_s g_pwmstate; void setup() { // put your setup code here, to run once: Serial.begin(115200); pwm_init(2000, 0.1); } float duty_c = 0.0; void loop() { // put your main code here, to run repeatedly: duty_c = duty_c + 0.01; if (duty_c > 1.0) { duty_c = 0.0; } pwm_output(0 , 2000, duty_c); pwm_output(1 , 2000, duty_c); pwm_output(2 , 2000, duty_c); pwm_output(3 , 2000, duty_c); delay(10); } void pwm_init(int freq, float duty) { if (!g_pwmstate.initialized) { g_pwmstate.duty = (uint32_t)(duty * 65535); g_pwmstate.freq = freq; g_pwmstate.initialized = true; } } void pwm_output(int pin_num, int freq, float duty) { int fd; int ret; struct pwm_info_s info; char* devpath; pwm_init(freq, duty); if (pin_num == 0) { devpath = "/dev/pwm0\0"; } else if (pin_num == 1) { devpath = "/dev/pwm1\0"; } else if (pin_num == 2) { devpath = "/dev/pwm2\0"; } else if (pin_num == 3) { devpath = "/dev/pwm3\0"; } else { devpath = "/dev/pwm0\0"; } if (g_pwmstate.devpath) { free(g_pwmstate.devpath); } g_pwmstate.devpath = strdup(devpath); fd = open(g_pwmstate.devpath, O_RDONLY); if (fd < 0) { close(fd); return; } info.frequency = freq; info.duty = (uint32_t)(duty * 65535); ret = ioctl(fd, PWMIOC_SETCHARACTERISTICS, (unsigned long)((uintptr_t)&info)); if (ret < 0) { close(fd); return; } ret = ioctl(fd, PWMIOC_START, 0); if (ret < 0) { close(fd); return; } close(fd); } ```