STM32F103+ServoMotorでSolarTrackerを作ってみた。(RTCバージョン)

最近、小型ソーラーパネルをポチッたのでソーラーパネルの発電の実験をしてみた。パネルの向きを決定するのが以外に面倒で簡単に太陽の方向に合わせる方法はないのかと調べてみたところ自作してる人がそれなりにいるようだ。その多くは光センサーによりパネルを太陽の方向に合わせる仕組みのようだが曇りや雨など暗いときに太陽の方法に向けることが難しそうに思える。暗いときにどっち向いてようが問題ないとは思うけどバグッてるようでカッコ悪いから計算で求めた太陽位置に向けるものを考えてみた。

太陽位置の計算(sun.h)は、株式会社気象データシステム様が公開されている拡張アメダス気象データ 内の技術解説一般【年差を考慮した太陽位置の簡易計算】のプログラムの一部をC言語に置き換えたものを利用しているがご厚意により正式に公開許可を頂けた。感謝。m(_ _)m

開発用にとアリエクスプレスで購入した製品と同じものがアマゾンでも売られているようだ。

Yahboom 2DOF サーボ回転PTZ,デジタルサーボ付き,リモートコントローラー,金属デジタル舵コントローラー,サーボコントローラー (2DOF metal servo with control board)

製品に含まれているボードはお手軽で便利だ。USB給電のみでも無負荷ならサーボを動作させられるしUSBシリアル接続で書き込みもできてしまう。汎用の開発ボードとしても利用できるかも。

ファームウェアも公開されている。HWタイマーで信号作って動作してるのかなと思ってコードを確認してみたらな~~んと割り込みを使ったソフトウェア制御だったりしてちょっと衝撃を受けてしまった。しかもOLED表示させるとコントローラー操作のレスポンスが劇的に悪化してしまう。このプログラムは見なかったことにしよう...(-_-;)

開発はSTMicroelectronicsが公開してるArduino用の”STM32 MCU based boards by STMicroelectronics”
を利用したがライブラリにサーボが含まれていたのでコードを確認したらこちらも割り込みを使ったソフトウェア制御だった。

サーボってソフトウェア制御するのが今時なのか?と一瞬思ってしまったがソフトウェア制御だとCPU負荷は高いし正確な信号が出せないからサーボがプルプル震えたりするんじゃね?とか余計なことを考えてしまった結果、ハードウェア制御するサーボライブラリも作ってみた。

ボードのサーボ信号出力ピンはTIM1/2/3/4/5/8の各HWタイマーの出力ピンに合わせてあるのでハードウェア制御するつもりだったけれど作れなくて諦めてしまったのだろうか...それはともかく24CH同時にHWタイマーでPWM駆動できるライブラリを作ることはできた。50Hzの標準的なサーボのパルス範囲である2000usを6400分割した分解能でパルスを作ることが可能だ。

それと時刻と設定値の保存用にEEPROM付きRTCモジュールを使ってみた。設定値をEEPROMに保存すればRTCモジュールを入れ替えるだけで時刻も設定も引き継がれるのでとても便利だ。

WINGONEER 小型DS3231 AT24C32 I2Cモジュール用の高精度リアルタイムクロックモジュール,ボタン電池付き(A145)

※充電回路付きであるためモジュールに電源供給する場合は付属のボタン電池(CR2032)を使ってはいけない。充電電圧に適合するのはLIR2032のみ。他のML2032などでは過充電となるため絶対に使ってはいけない。
※DS3231/AT24CXX用のライブラリも新たに作成。

日付の設定は一度だけ必要。Arduino-IDEのシリアルモニターや端末などから”calendar 2024-08-06 12:00:00″の形式で現在時刻を送信すればOKだ。その他、各種パラメタも設定することができる。

【コマンド一覧】
calendar yy-mm-dd HH:MM:SS
latitude n
longitude n
longitude_std n
servo1.ch n
servo1.range n
servo1.min n
servo1.max n
servo2.ch n
servo2.range n
servo2.min n
servo2.max n
load
save
reset
config
debug [0 | 1]
turn [auto | min | center | max]
rtc +-n

※設定値を変更した後保存するにはsaveコマンドを実行し変更内容を適用するにはresetコマンドを実行する。

【動作実験中の様子】


【修正履歴】
2024-08-26
初めてDS3231を使ってみて一日数十ミリ秒程度の誤差には収まってはいるので特に不満はないのだが、GPSモジュールも入手しやすくなってるようなので調整する必要のないGPSクロックにしたほうがいいのかもと思う今日この頃...
あと、AT24C1024に対応してみた。試験してないけど。

2024-08-24
sun.hのSun::timeZoneOffset()をより汎用的な実装に変更。それと年の経過日(dayOfYear)が1からになっていたので0からに修正。

2024-08-23
株式会社気象データシステム様より太陽位置計算プログラムの公開許可を頂いた。
DS3231の誤差の件はようやく確認がとれた。PCの時刻と比較していたがPCの時刻にもかなりの誤差があったりして確認に手間取っていたがDS3231のAgingOffsetにより0.1-0.2ppm程度まで誤差を調整することができるようだ。

2024-08-22
DS3231ライブラリの仕様変更。

2024-08-21
DS3231ライブラリの仕様変更。

2024-08-20
DS3231ライブラリの機能追加とエラー処理の強化。起動時のサーボの動き方を変更。

2024-08-18
DS3231ライブラリをアラーム割り込みに対応。SQW(1Hz)を利用したDS3231のアラーム機能のエミュレーションなので下記のどちらかの方法でSQW(1Hz)設定とそのGPIOピン指定が必要。

DECLARE_DS3231(Wire) rtc;

rtc.begin(SQWピン番号)

or

rtc.begin();
rtc.outputSQW(rtc.SQWRATE_1);
rtc.emuratin(SQWピン番号);

2024-08-17
もう少し様子見する必要はあるがDS3231の誤差が大きい件は解決したかもしれない。
一秒に一回リードするだけでも時刻に影響を与えるようなのでDS3231ライブラリを修正し起動時に一回だけリードした後はDS3231のSQW(1Hz)信号によるGPIO割り込み処理にて日付更新していく方法に変更してみた。これで暫く様子をみてみよう。

2024-08-16
本当のことかどうかは確かめてないけどDS3231の頻繁なリードにより時刻が狂うという記事を見つけたので念の為その対策を行った。
DS3231のSQW(1Hz)出力により一秒に一回だけDS3231をリードするようにDS3231ライブラリを改良してみた。
しかし、想定外にDS3231の誤差が大きすぎるようだ。データシート通りの2ppmの誤差なら最大でも5-6日で一秒狂う計算になるはずが一日で一秒以上狂うし、エージングオフセットでも調整しきれないくらいの誤差だし、秒のタイミングが安定してないような気もするし...不良チップ或いはfakeチップなのだろうか?それとも何らかの外部的要因によるものなのか?とりあえずめいっぱい補正かけて一日0.5秒程度の誤差にはなったのだが根本的な原因が知りたいところだ。

2024-08-15
サーボ位置の微調整用のコマンドとRTC誤差補正コマンドを追加。AT24CXXのwriteメソッドがページ境界をまたがる書き込みをしたときの不具合を修正。

2024-08-14
軽微な最適化を行った。

2024-08-12
DS3231/AT24CXXに対応。その他バグ修正。

2024-08-09
高さの角度を0-90度に制限していたが赤道付近の地域など90度を前後する地域がありそうなので0-180度に設定変更。その他、メソッド名の変更など若干の修正を行った。

【スケッチ】

【ライブラリ】
サーボ・ライブラリはbegin()の最小パルス幅(pulsemin)/最大パルス幅(pulsemax)引数を逆に指定することで回転方向が逆になる。
回転範囲の制限は角度値(angle)を調整するのではなくbegin()の最小パルス幅(pulsemin)/最大パルス幅(pulsemax)引数で調整すべき。
分解能を上げたいときは回転範囲(anglerange)を大きくする。6400を指定すると最大分解能となる。それ以上を指定することもできるが分解能的には意味がない。
サーボの制御信号タイミングはHWタイマー毎に同じなので制御タイミングが重要ならHWタイマー毎に4個ずつサーボをペアにすること。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください