質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

解決済

2回答

1278閲覧

Attiny13A スリープモードから復帰後にmicros()関数を使う方法

gge

総合スコア10

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

0クリップ

投稿2022/01/18 14:34

編集2022/01/18 14:53

Attiny13Aにて、スリープモード(SLEEP_MODE_PWR_DOWN)から復帰した後、micros()関数が意図通り機能しません。
スリープ後にもmicrosを使う方法を教えていただけないでしょうか?

スリープモードから復帰後、PB0を3秒間HIGHにしたいのですが、スリープ後はPB0が一瞬だけHIGHになり、すぐにLOWになってしまいます。
なお、電源投入後からスリープ前の初回のLED()は問題なく動作します。
また、"micros"の代わりに"delay"を使うと問題なく動作します。

タイマー関連のレジスタの設定が原因かと思いましたが、解決方法を見つけることができませんでした。
よろしくお願いいたします。

使用ツール: Arduino IDEのMicroCore + Arduino Nano (互換品)

ArduinoIDE

1#include <avr/sleep.h> 2#include <avr/interrupt.h> 3 4void setup() { 5 DDRB = 0b00000001; 6 PORTB = 0b00010000; 7 set_sleep_mode(SLEEP_MODE_PWR_DOWN); 8} 9 10// スリープモード 11void Sleep() { 12 GIMSK |= _BV(PCIE); 13 PCMSK |= _BV(PB4); 14 sei(); 15 sleep_enable(); 16 sleep_cpu(); 17 cli(); 18 sleep_disable(); 19 GIMSK &= ~_BV(PCIE); 20 PCMSK &= ~_BV(PB4); 21} 22 23ISR(PCINT0_vect) { 24} 25 26// 3秒間PB0をHIGH 27void LED(){ 28 PORTB |= _BV(PB0); 29 unsigned long t = micros(); 30 while (micros() - t < 3000000); // ここを「delay(3000)」に置き換えると問題なし。 31 PORTB &= ~_BV(PB0); 32} 33 34void loop() { 35 LED(); // 初回のLED()は問題なく作動する。2回目以降は一瞬でPB0がLOWになる。 36 Sleep(); 37}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2022/01/18 23:27

> タイマー関連のレジスタの設定が原因かと思いましたが で、タイマー関連のレジスタ内容を何らかの方法で確認したのですか?
nac_tnk

2022/01/19 14:15

一応確認しておくけど、ちゃんと「Micros Enabled」にはしてるよね?
gge

2022/01/20 02:54

ご質問ありがとうございます。 Micros Enabledには設定しています。 スリープ前はmicrosは問題なく動作しているので、スリープモードがトリガーとなって動作不良が発生しているのかと思います。
guest

回答2

0

自己解決

cli()をISR(PCINT0_vect)の中に移動させることで不具合が解消しました。

調べたところによると、ISR内でmicrosを使うと動作不良を起こすそうです。
cli()のタイミングを変えることで動作不良が解消したことから、タイマー0のオーバーフロー絡みが原因だったのではないかと考えております。

【参考URL】
https://arduino.stackexchange.com/questions/22212/using-millis-and-micros-inside-an-interrupt-routine

ご協力ありがとうございました。

ArduinoIDE

1#include <avr/sleep.h> 2#include <avr/interrupt.h> 3 4void setup() { 5 DDRB = 0b00000001; 6 PORTB = 0b00010000; 7 set_sleep_mode(SLEEP_MODE_PWR_DOWN); 8} 9 10// スリープモード 11void Sleep() { 12 GIMSK |= _BV(PCIE); 13 PCMSK |= _BV(PB4); 14 sei(); 15 sleep_enable(); 16 sleep_cpu(); 17 //cli(); この部分を削除 18 sleep_disable(); 19 GIMSK &= ~_BV(PCIE); 20 PCMSK &= ~_BV(PB4); 21} 22 23ISR(PCINT0_vect) { 24 cli() // ここにcli()を移動させることで不具合解消 25} 26 27// 3秒間PB0をHIGH 28void LED(){ 29 PORTB |= _BV(PB0); 30 unsigned long t = micros(); 31 while (micros() - t < 3000000); // ここを「delay(3000)」に置き換えると問題なし。 32 PORTB &= ~_BV(PB0); 33} 34 35void loop() { 36 LED(); // 初回のLED()は問題なく作動する。2回目以降は一瞬でPB0がLOWになる。 37 Sleep(); 38}

投稿2022/01/25 09:45

gge

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

micros関数の仕様がよくわかりませんが、復帰後のmicros関数の戻り値がどうなってるのか確認してみては

投稿2022/01/18 14:59

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gge

2022/01/18 23:57

ご回答ありがとうございます。 ATTINYのシリアル通信の環境が整っていないので時間がかかってしまいそうですが、確認してみます。
y_waiwai

2022/01/19 02:19

そいつのソース見てたりするとグローバル変数使ってたりするんで、復帰直後にmicrosいっぺん実行しとけばいいんかなと思ったりしますが。 まあとにかくきちんと原因というのを追求しときましょう
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問