「PIC AVR 工作室」サイトの日記的なブログです。
サイトに挙げなかった他愛ないことを日記的に書き残してます。
PIC AVR 工作室 ブログ



先日の↓
http://brown.ap.teacup.com/nekosan0/210.html
 「外部リファレンスの参照も対応していたんですね。」
で書いたことについて、もうちょっと調べてみました。

通常のmega168(やmega88、mega48)を電源オン
した時と、arduinoでコンパイルしたプログラムを
実行した時、デフォルトでそれぞれ内部レジスタが
どのように設定されるかについてです。


arduinoについては以前書いたように、DEFAULT
として内蔵5Vが参照電圧として適用されますが、
mega168のデータシートを読むと、デフォルトは
AREF端子入力からの参照電圧となっています。

通常mega168で独自のプログラムを組む場合、
AREF電圧では無く内蔵参照電圧を使う場合には
明示的にレジスタを設定しないとならない
のですが、arduinoの場合は「簡単に使える」
ということが優先されたのか、DEFAULTで
内蔵参照に設定されてしまっています。
このことが厄介を呼んでいるようですね。


ちなみに、データシートをちゃんと読むと、
251ページの「23.5.2 ADC Voltage Reference」
の項目に
 ・AREFに外部参照用の機器を繋いでいる時は、
  ショートしちゃうので他の参照用オプションは
  使用できません。
と書いてありました。ちゃんとデータシート
読まないといけませんね(´o`)。

ちなみに、AREF端子がわざわざこういう特殊な
繋ぎ方になっているのは、1.1Vや5Vの内蔵参照電圧
を使うときにでも、AREF端子とGNDの間にパスコンを
入れることで参照電圧からノイズを取り除く事が
出来るようにという配慮みたいです。


それにしてもarduino。
一切外部参照電圧を使うことは出来ない仕様と
考えるのが自然でしょう。
なぜそういう方針にしたんだろう???



コメント ( 2 )
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする




以前秋月で買ったまま死蔵状態だったLM35も
見つかったので、
http://brown.ap.teacup.com/nekosan0/203.html
↑このS8100Bに引き続き、LM35も使ってみました。

ちなみに、今秋月でLM35買うと150円らしいんですが、
手元の死蔵品の値札見たら250円…(TへT)


ピン配置はS8100Bとは異なり、こんな感じ。


ちなみにLM35は0℃の時に0V、1℃上がる毎に10mV
上昇するというICです。計算が凄く簡単なのですが、
AVR-AT-mega168のADコンバーターは内蔵の参照電圧が
1.1Vとあまりキリのいい電圧では取り込めないのが難点。
(mega8なら参照電圧が2.56Vなのでキリがいいのに)

まぁ、簡単な変換式で変換できるので、計算で求める
事にします。以下にスケッチを。

int ledPin = 3; // select the pin for the LED
int analogpin0 = 0; // select the pin for analog0 input

int data = 0; // input data from ADC
int summary = 0; // summary of input data
int i;

double t_value; //temperature value

int t_1;
int t_2;


void setup() {
analogReference(INTERNAL); //use internal 1.1v reference
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
Serial.begin(9600);

Serial.println("start");
}


void loop() {

digitalWrite(ledPin, HIGH);
delay(1800);

summary = 0;
for(i=0;i
LM35に使う電源は、例によってreduino-nanoのVcc、
GNDの各ピンから取ってます。

ちなみに、LM35は出力インピーダンスがS8100Bより
低いせいか、パスコンを入れなくても電圧は
安定しているようです。


それにしても、mega168の内部参照電圧が1.1Vって
いうのがちょっとねぇ…。
精度が1.1V±0.1Vという話なので、誤差が10%ちかく
生じる計算になります。小さい電圧なので相対誤差が
大きくなるわけですよ。


そうそう。氷点下を計測する時にはそのままでは
計測できないので補整回路が必要になるんですが、
回路は秋月のデータシートに載ってます。

問題は、このICは電源電圧4V以上で動作するので
秋月データシートに書いてあるやり方を使うとすると
5V電源では電圧が足りないようです。
その場合は、もっと高い電圧を使用するか、
S8100Bを使うか、どちらかの対応が必要に
なりそうです。



コメント ( 0 )
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする




せっかくサーボモーターが発掘されたので、
arduinoでサーボモーターを使って遊んでみました。

まずは、私の愛機reduino-nanoのメーカー、
マイクロファンのサイトで公開されている↓これ。
http://www.microfan.jp/?cat=78

手元のサーボモーターもフタバ互換のピン配置
だったので、例に習ってCN3にそのままジャックを
差し込みます。
スケッチも特に修正不要。このまま動きます。

2つのボタン(リセットじゃないヤツ)を押すと、
サーボモーターがグリグリ動きました。
よし、よし。
ちなみに、動作風景はこんな感じ。



次、ライブラリその1。「Servo」を使ってみます。
例によってライブラリのzipファイルをダウンロード
したら、解凍して\hardware\librariesのフォルダに
放り込み、arduino-IDEを起動します。
そして以下のようにスケッチを入力。(サンプル
はサーボを2つ繋ぐようなものだったので、1個だけ
繋ぐように修正しました)

#include <Servo.h>

Servo servo1;

int servoPin = 10;


void setup(){
servo1.attach(servoPin);
//servo1.setMaximumPuls(2000);

Serial.begin(9600);
Serial.print("Ready");
}


void loop(){
static int v = 0;

if ( Serial.available()) {
char ch = Serial.read();

switch(ch) {
case '0'...'9':
v = v * 10 + ch - '0';
break;
case 's':
servo1.write(v);
v = 0;
break;
}
}

Servo::refresh();

}

(例によって、#include文には半角不等号の
 代わりに全角不等号を入れてあります。
 適宜直して使ってください)

これといって難しいところは無いんですが、
マイクロファンのサンプルプログラムが
直接ミリ秒指定で制御していたのに対し、
このライブラリを使用すると「角度」で
指定できるようです。PC側からシリアル
通信でコマンドを送ることで角度を変更
出来るスケッチです。
例えば、「90s」と打てば90°に設定されます。

ただこのライブラリ、setMaximumPulsメソッド等で
可動範囲を指定しておく必要があるようです。
(製品の仕様差をここで吸収しているんでしょう)

サーボを繋ぐピンはデジタルピンならどこでも
良いみたいですが、一点注意が必要。
少なくとも50m秒以内に1回、Servo::refresh()を
呼び出ししないといけないようです。
ライブラリの中身を覗いてないので何故かは
よく解ってません。まあ、サンプルスケッチに
従ってそのようにしてみます。

うん。動きました。


次、ライブラリその2。「Servotimer1」です。

avrのtimer1を占有してしまいますが、ハードウェア
処理で制御されるようです。
先ほどのライブラリと違って、Servo::refresh()を
定期的に呼び出す必要は無いという点と、
利用可能なピンが固定されてしまうという点
について注意が必要です。

さて、スケッチはこんな感じ。

#include <ServoTimer1.h>

ServoTimer1 servo1;

void setup()
{
pinMode(1,OUTPUT);
servo1.attach(10);
servo1.setMinimumPulse(750);
// not "setMinimumPulseWidth"
servo1.setMaximumPulse(2300);
// not "setMaximumPulseWidth"
Serial.begin(9600);
Serial.println("Ready");
}

void loop()
{
static int v = 0;

if ( Serial.available()) {
char ch = Serial.read();

switch(ch) {
case '0'...'9':
v = v * 10 + ch - '0';
break;
case 's':
servo1.write(v);
v = 0;
break;
}
}
// Notice that no ServoTimer1::refresh() is needed.
}

ライブラリの解説サイトに間違い発見!
上記のスケッチにコメントでも記入してますが、
0度、180度におけるパルスの長さはそれぞれ
setMinimumPulseWidth、setMaximumPulseWidth
で指定するように書かれていますが、コンパイル
エラーになっちゃいます。
ライブラリの中身を見るとすぐ判りますが、
正しくはsetMinimumPulse、setMaximumPulse
です。

なお、接続するサーボモーターによっては
大量の電流を使用してしまいます。
でもUSBは500mAまでしか取れません。
大型のサーボを使用する場合は別途電源が必要
です。

ちなみにreduino-nanoであればポリスイッチで
500mA以上流れたら遮断されるので、あまり
神経質になる必要はないと思います。
(突如遮断されるので、USB-シリアル変換機能
 も切れてしまうので、windowsアプリ側から
 見たら突如シリアルポートが無くなるという
 状態になるので、変なことにはなると思いますが、
 PCやreduino-nanoが壊れることはないでしょう)

個人的には、ライブラリその1としてご紹介した
「Servo」のライブラリが気に入りました。
接続するピンがどこでも言いという点と、
デジタルピンがあいている限り幾つでもサーボを
繋ぐことが可能だということ。

応用範囲が一番広いのはこれでしょう。

あとでサイト上にもう少しちゃんとまとめておきたい
と思います。

(追記:サイトのほうに情報を纏めました↓)
http://nekosan0.bake-neko.net/library_servo.html



コメント ( 3 )
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする