• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:30~60秒に1回モーターを回したい)

30秒~60秒に1回モーターを回したい

このQ&Aのポイント
  • 古いH8のマイコンが載った車型ロボットで、30秒~60秒に1回ランダムにモーターを前後に回したいがうまく動かない。
  • C言語のコードを書いてHEWとFDTで読み込ませ、動かしているが、いつも32秒±1秒まで待ってから動き始める。さらに、プログラム上では前後の動きは30秒~60秒に1回のはずだが、8回や10回の繰り返しをした後、次の32秒±1秒のルーチンに入る。
  • 何がおかしいのか分からず、データシートを見つけたが、どこを見れば良いのか分からない。タイマーの上限時間に関する情報も見つけられていない。疑似乱数の生成方法についても今回は問題ないので、今はそれに関しては気にしない。

質問者が選んだベストアンサー

  • ベストアンサー
  • TIGANS
  • ベストアンサー率35% (245/681)
回答No.2

>r = rand() % 30000;//0~29,999の乱数を生成する…はず int rand(void) は、0からRAND_MAXの間の擬似乱数整数を生成します。 H8の<stdio.h>では、RAND_MAX=32767に定義されていますので %30000の結果は 0~2767が2768~29999の2倍頻度あらわれることになり、30~32.8秒の頻度があがりますよ。 一方 >int r = 30000; (←もしかして、RAND_MAXと勘違いしてる?) >srand(r); で、ランダムシードを毎回30000に固定して設定しているので そのシードから生成される乱数系列が、 質問文のような動作になる乱数系列だったのではないでしょうか。

sucker
質問者

お礼

解決しました。 原因はWait()のカウンターの上限が32,767であることでした。 Wait(32767)を挟むと32.767ms待ってからモーターが回ります。 Wait(32768)を挟むと何も待たずにモーターが回り続けます。 それに気付いたのはNo.2さんの「RAND_MAX=32767」という回答でした。 そんなに小さいんですね…「RAND_MAX=2147483647=0x7fffffff」だと思って組んでました。 解決法としては、Wait()を分割しました。 最初に必ず30秒待ちたいので、Wait(30000);とし、 その後で乱数分待つことにしました。 >%30000の結果は 0~2767が2768~29999の2倍頻度あらわれることになり、30~32.8秒の頻度があがりますよ。 今回の主原因ではなかったですが、確かに偏りますね。 それを受け、今回は30までの乱数を生成し、それを1000倍することにしました。 >>int r = 30000; (←もしかして、RAND_MAXと勘違いしてる?) >>srand(r); >で、ランダムシードを毎回30000に固定して設定しているので いえ、実はint r = 30000;はループの外にあり、ループの中ではrは r = rand() % 30000; で毎回更新されています。なので固定ではないですね、毎回同じパターンにはなりますけど。 参考までに完成したコードを貼っておきます: void main(void) { //制御周期の設定[単位:Hz 範囲:30.0~] const BYTE MainCycle = 60; Init((BYTE)MainCycle); //CPUの初期設定 Mtr_Run(0,0,0,0); //モータを停止 LED(2); //オレンジのLED点灯 //ループ while(1) { //メインループ if(getSW()) { //スイッチが押されたら int r = 123; int waitTime = 0; srand(r); while(1) { //Wait(32767); //待つ //Wait(32768); //待たない Mtr_Run(-64,64,0,0); //前に進む Wait(500); Mtr_Run(64,-64,0,0); //後ろに下がる Wait(500); Mtr_Run(0,0,0,0); //モータを停止 Wait(30000); //30秒待つ r = rand() % 30; //0~29の乱数を生成する Wait(r * 1000); //30秒~60秒待つ } } } } …ありがとうございました。

その他の回答 (1)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

>srand(r); これって乱数の種を発生させる関数ですよね。 ならば、ループの中で毎回実行するのはまずいのでは? プログラムの開始時に「1回だけ」実行するのが正しい、と思います。

sucker
質問者

お礼

今回の主原因ではなかったですが、確かに一回で事足りましたね。 実は原因が疑似乱数にあるのかと思い、発生した乱数を種に次の乱数を発生させてみました。 まぁ、同じパターンにはなるんですが、解決の糸口にならないかと試行錯誤したまでです。 <time.h>が使えるといいんですけどね…。 ありがとうございました。

関連するQ&A