|
setup diary |
この間、デジットで買ったOPTREXのPWB842Bという液晶をようやく動かすことができた。いろいろとバグがあって発見に手間取ってしまった。まずwaitをかなり入れないとuPD7225がうまく応答しない。ICの説明書は一応読んだが、数マイクロ秒待てば良いような感じだったと思うが、100マイクロ秒ぐらいのwaitをいろいろなところに入れた。次に発見に手間取ったのが、i++のようなつもりで、i>>1としていたが、当然のことながらi>>=1としなければいけなかった。
さて、この液晶を何に使うかを考えていたのだが、磁気センサーを作ることにした。ホール素子の電圧をattiny261のADコンバーターを使って読んで、さらに液晶と通信して表示すれば、ワンチップの磁気センサーができあがるはずである。というわけで、プログラムを書いてみた。そのままだと精度が出ないようだったので、256回測定してその平均を取ったが、数値が安定して良い感じになった。磁場の絶対値に関しては、換算がまだ間違っているかも知れないが、1-1000ガウスぐらいは測定できるようになった。100以上では増幅をしないようにプログラムすれば、3Tぐらいまでは測れるようになつはずだろうが、面倒なので組み込んでいない。本当は、超伝導磁石の漏れ磁場を測定したかったのだが、どうやら感度の問題で難しいようだ。
#include <avr/io.h> #include <avr/interrupt.h> #define F_CPU 1000000 /* 1MHz */ #include <util/delay.h> #include <avr/pgmspace.h> /* lcd controller for OPTREX PWB842B */ /* 7seg 10digit */ // pin connection // 1 /RESET // 2 /SCK // 3 SI // 4 /BUSY // 5 C,/D // 6 /CS // 7 Vdd 5V // 8 Vss GND #define LCD_PORT PORTB #define LCD_PIN PINB #define LCD_DDR DDRB #define LCD_RESET 6 #define LCD_SCK 5 #define LCD_SI 4 #define LCD_BUSY 3 #define LCD_CD 2 #define LCD_CS 1 #define setbit(PORT,BIT) PORT|=_BV(BIT) #define clearbit(PORT,BIT) PORT&=~_BV(BIT) #define checkbit(PORT,BIT) (PORT&_BV(BIT)) #define SIZE_BUF 10 #define SIZE_CHAR 10 volatile uint8_t buf[SIZE_BUF]; // data to send LCD static volatile uint8_t chars[SIZE_CHAR]; // charactor data static volatile int32_t ave=0; static volatile uint16_t cnt=0; #define SIZE_AVE 256 #define ZERO_ADJ 6 const prog_uint8_t number[0x40]={ // 76543210 0b000000000, // 0x20 0b0, //! 0x21 0b001000001, //" 0x22 0b0, //# 0x23 0b0, //$ 0x24 0b0, //% 0x25 0b0, //& 0x26 0b001000000, //' 0x27 0b011001000, //( 0x28 0b000001011, //) 0x29 0b0, //* 0x2a 0b0, //+ 0x2b 0b0, //, 0x2c 0b000010000, //- 0x2d 0b000000100, //. 0x2e 0b010010001, /// 0x2f // 76543210 0b011101011, //0 0x30 0b000000011, //1 0x31 0b010111001, //2 0x32 0b000111011, //3 0x33 0b001010011, //4 0x34 0b001111010, //5 0x35 0b011111010, //6 0x36 0b000001011, //7 0x37 0b011111011, //8 0x38 0b001111011, //9 0x38 0b0, //: 0x3a 0b0, //; 0x3b 0b001011000, //< 0x3c 0b000011000, //= 0x3d 0b000011001, //> 0x3e 0b000111001, //? 0x3f // 76543210 0b010111011, //@ 0x40 0b011011011, //A 0x41 0b011110010, //B 0x42 0b010110000, //C 0x43 0b010110011, //D 0x44 0b011111000, //E 0x45 0b011011000, //F 0x46 0b011101010, //G 0x47 0b011010010, //H 0x48 0b000000010, //I 0x49 0b010100011, //J 0x4a 0b011010001, //K 0x4b 0b011100000, //L 0x4c 0b010011010, //M 0x4d 0b010010010, //N 0x4e 0b010110010, //0 0x4f // 76543210 0b011011001, //P 0x50 0b001011011, //Q 0x51 0b010010000, //R 0x52 0b001010010, //S 0x53 0b011110000, //T 0x54 0b010100010, //U 0x55 //0b011100011, //V 0x56 0b011110011, //V 0x56 //0b001110001, //W 0x57 0b010101010, //W 0x57 0b011010011, //X 0x58 0b001110011, //Y 0x59 0b010010001, //Z 0x5a 0b011101000, //[ 0x5b 0b0, //\ 0x5c 0b000101011, //] 0x5d 0b001001001, //^ 0x5e 0b000100000 //_ 0x5f }; void lcd_write(uint8_t *s,char n){ unsigned char i,c; _delay_us(50); clearbit(LCD_PORT,LCD_CS); _delay_us(100); // wait at least 1.5us do{ c=*(s++); while(checkbit(LCD_PIN,LCD_BUSY)==0){} _delay_us(100); for(i=1<<7;i!=0;i>>=1){ clearbit(LCD_PORT,LCD_SCK); _delay_us(50); if((c&i)!=0){setbit(LCD_PORT,LCD_SI);} else{clearbit(LCD_PORT,LCD_SI);} _delay_us(50); setbit(LCD_PORT,LCD_SCK); _delay_us(50); } _delay_us(50); // wait at least 3us in total }while((--n)>0); while(checkbit(LCD_PIN,LCD_BUSY)==0){} setbit(LCD_PORT,LCD_CS); _delay_us(50); } void lcd_init(){ uint8_t commands[6]={ 0b01001000, // mode_set 0b00110001, // synchronized transfer 0b00100000, // clear data memory 0b00011000, // blinking off 0b00010001, // display on 0b00010100, // without segment decoder }; LCD_DDR|=(1<<LCD_RESET)|(1<<LCD_SCK)|(1<<LCD_SI)|(1<<LCD_CD)|(1<<LCD_CS); LCD_DDR&= ~(1<<LCD_BUSY); LCD_PORT|=(1<<LCD_RESET)|(1<<LCD_SCK)|(1<<LCD_SI)|(1<<LCD_CD)|(1<<LCD_CS); // LCD_PORT|=(1<<LCD_BUSY); _delay_us(100); clearbit(LCD_PORT,LCD_RESET); _delay_us(100); setbit(LCD_PORT,LCD_RESET); _delay_us(200); setbit(LCD_PORT,LCD_CD); _delay_us(100); lcd_write(commands,6); } void buf_clear(){ unsigned char i; for(i=0;i<SIZE_BUF;i++){buf[i]=0x00;} } void buf_display(){ clearbit(LCD_PORT,LCD_CD); _delay_us(100); lcd_write((uint8_t*)buf,SIZE_BUF); } void char_set(char n,unsigned char c){ chars[n]=c; if(c<0x20 || c>0x7f){c=0x20;} buf[n]=pgm_read_byte(&number[c-0x20]); } void char_shift(char s){ unsigned char n; for(n=SIZE_CHAR-1;n>0;){ char_set(n,chars[--n]); } char_set(0,s); } void string_set(char *s){ unsigned char c; for(c=SIZE_CHAR;c>0;){ char_set(--c,*(s++)); } buf_display(); } void string_shift(char *s,char l){ for(;l>0;l--){ char_shift(*(s++)); buf_display(); _delay_ms(500); } } void disp_num(unsigned char c){ unsigned char i; i=c>>4; char_shift(i+((i<10)?0x30:0x37)); i=c&0x0f; char_shift(i+((i<10)?0x30:0x37)); buf_display(); } // AD converter void ad_init(){ clearbit(ADCSRB,REFS2); // 1.1V setbit(ADMUX,REFS1); // 1.1V clearbit(ADMUX,REFS0); // 1.1V setbit(ADMUX,ADLAR); // bit6-15 setbit(ADCSRB,MUX5); // clearbit(ADMUX,MUX4); // clearbit(ADMUX,MUX3); // clearbit(ADMUX,MUX2); // clearbit(ADMUX,MUX1); // clearbit(ADMUX,MUX0); // setbit(ADCSRA,ADPS2); // CK/128 setbit(ADCSRA,ADPS1); // CK/128 setbit(ADCSRA,ADPS0); // CK/128 setbit(ADCSRA,ADEN); // enable setbit(ADCSRA,ADIE); // interupt enable setbit(ADCSRB,BIN); // bipolar setbit(ADCSRB,GSEL); // gain 32/20 } ISR(ADC_vect){ int16_t v; uint8_t s[10]; v=ADCL; v|=ADCH<<8; v-=ZERO_ADJ<<6; // zero adjust if(ave<0){v=-v;ave-=v>>6;} else{ave+=v>>6;} if(++cnt>=SIZE_AVE){ if(ave<0){ave=-ave;s[0]='-';} else{s[0]=' ';} ave/=(SIZE_AVE/2); s[9]=' '; s[8]='E'; s[7]='0'; s[6]=' '; s[5]=ave%10+0x30; ave/=10; s[4]=ave%10+0x30; ave/=10; s[3]=ave%10+0x30; ave/=10; s[2]=ave%10+0x30; ave/=10; s[1]=ave%10+0x30; string_set(s); ave=0; cnt=0; } } int main(){ _delay_ms(500); lcd_init(); buf_clear(); buf_display(); ad_init(); sei(); for(;;){ setbit(ADCSRA,ADSC); // enable while(checkbit(ADCSRA,ADSC)!=0){_delay_us(1);} _delay_us(10); } }