目次
前
次
3相交流信号生成
技術者の知人から、3相交流信号をマイコンで生成できた
とオシロスコープの静止画が送られてきました。
廃棄した冷凍庫の中に、3相交流信号を生成して
コンプレッサを動かしていました。
これに触発されて、Arduinoで3相交流信号を生成
します。
3相交流信号は、正弦波を3個生成し、位相差を
120度、240度とする。
この仕様で考えると、正弦波の1周期を配列に格納し
カウンタで値を出力するなら、3つのカウンタで配列
から取り出してくる値を変えればいけるはず。
正弦波の1周期を128として、正弦波の波形を
配列に格納。それをカウンタ値が+1される都度
引き出して、出力。
単純な考え方でよいのですが、ArduinoはD/A変換器を
もっていないので、正弦波の値を生成できたとしても
出力する術がないと思い勝ちです。
PWMを利用すると、デジタル値をアナログ値へと変換
できるので、D/A変換器の代用で使う。
この手を利用して、次のコードを考えました。
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* calculate */
i = state ;
k = (i + 42) & 0x7f ;
j = (i + 85) & 0x7f ;
uu = *(stbl+i);
ww = *(stbl+j) ;
vv = *(stbl+k) ;
/* impress */
if ( tflag == ON ) {
analogWrite(UP,uu);
analogWrite(VP,vv);
analogWrite(WP,ww);
} else {
PORTB = 0x00 ;
}
/* update */
state++ ;
state &= 0x7f ;
}
関数analogWriteは、D/A変換で利用できるので
3つの端子から正弦波を出力。
U PB1
V PB2
W PB3
analogWriteは、PWMを利用するので、正弦波を出力する
ピンを、次のように決めました。
変数i、j、kを利用して、iから位相差に相当する
値を加えてj、kの値を生成。
j、kは0から128の範囲に収まるように128で
割った余りを代入しておきます。
正弦波は、中央値を電源電圧の半分とし、中央値から
上下に振れるように考えます。
正弦波の値を、配列に格納する処理は、以下。
for ( i = 0 ; i < BSIZE ; i++ ) {
*(stbl+i) = (byte)(127*(sin(i*PI/64)+1));
}
予期しない時に、正弦波を出力しないようにモニタを
入れて対応します。
モニタで使うコマンドは、次のように決定。
- ? help
- G enable
- g disable
正弦波を出力するか停止するのかをフラグtflagで
制御できるようにしておきます。
コマンドインタプリタは、次のように定義。
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf() ;
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help(); }
/* enable */
if ( cmd == 'G' ) {
state = 0 ;
tflag = ON ;
}
/* disable */
if ( cmd == 'g' ) { tflag = OFF; }
}
文字出力、文字列出力、改行および受信割込みハンドラは
以下でよいでしょう。
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *ptr)
{
while ( *ptr ) {
rs_putchar( *ptr );
ptr++;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("G enable") ; crlf();
rs_puts("g disable") ; crlf();
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
まとめると、以下。
#include <MsTimer2.h>
#include <math.h>
#define OFF 0
#define ON OFF+1
#define XINTERVAL 10
#define BSIZE 128
#define UP 9
#define VP 10
#define WP 11
/* function prototype */
void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
/* variables */
boolean tflag ;
boolean eflag ;
boolean uflag ;
byte state ;
byte sbuf[8] ;
byte sindex ;
byte cmd ;
byte i ;
byte j ;
byte k ;
byte stbl[BSIZE] ;
byte uu ;
byte vv ;
byte ww ;
void setup()
{
/* initialize serial */
Serial.begin(9600);
sindex = 0 ;
rs_puts("Hello !");
crlf();
/* clear flags */
tflag = OFF ;
eflag = OFF ;
uflag = OFF ;
/* initialize port values */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x00 ;
/* initialize port direction */
DDRB = 0xff ;
DDRC = 0xff ;
DDRD = 0xfe ;
/* variables */
state = 0 ;
for ( i = 0 ; i < BSIZE ; i++ ) {
*(stbl+i) = (byte)(127*(sin(i*PI/64)+1));
}
/* 5ms period */
MsTimer2::set(XINTERVAL,update_trigger);
/* enable */
MsTimer2::start();
}
void loop()
{
/* command interpreter */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* new line */
crlf() ;
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help(); }
/* enable */
if ( cmd == 'G' ) {
state = 0 ;
tflag = ON ;
}
/* disable */
if ( cmd == 'g' ) { tflag = OFF; }
}
/* handling */
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* calculate */
i = state ;
k = (i + 42) & 0x7f ;
j = (i + 85) & 0x7f ;
uu = *(stbl+i);
ww = *(stbl+j) ;
vv = *(stbl+k) ;
/* impress */
if ( tflag == ON ) {
analogWrite(UP,uu);
analogWrite(VP,vv);
analogWrite(WP,ww);
} else {
PORTB = 0x00 ;
}
/* update */
state++ ;
state &= 0x7f ;
}
}
void update_trigger()
{
/* set flag */
eflag = ON ;
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("G enable") ; crlf();
rs_puts("g disable") ; crlf();
}
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *ptr)
{
while ( *ptr ) {
rs_putchar( *ptr );
ptr++;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
目次
前
次