//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ブレッドボード用電圧電流計 // [2014/03/20 08:30:56] ver 1.0.0 プログラ開始 // [2014/03/21 16:26:43] ver 1.0.1 切削基板用 // [2014/03/22 06:32:52] ver 1.0.2 EEPROM 書込み確認 // [2014/03/22 07:19:05] ver 1.0.3 使用電圧設定 // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // #include <16F88.h> #device adc=10 // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // #FUSES NOWDT //No Watch Dog Timer #FUSES PUT //Power Up Timer #FUSES INTRC_IO //Internal RC Osc, no CLKOUT #FUSES NOBROWNOUT //No brownout reset #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O #use delay(int=8000000) // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // // #use FIXED_IO( A_outputs=PIN_A6,PIN_A4,PIN_A2 ) // #use FIXED_IO( B_outputs=PIN_B5) // // I2C LCD 用に使用 #use i2c(Master,Fast,sda=PIN_B4,scl=PIN_B5) // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // IO ピンの指定 // #define chAmp 0 // 電流検出 AD チャンネル #define chVolt 1 // 電圧検出 AD チャンネル #define chTemp 3 // 温度検出 AD チャンネル // #define kRedLED PIN_A2 // 赤色LED #define kBlueLED PIN_A4 // 青色LED #define kPowerOut PIN_A6 // ブレットボードへの電力供給を制御するピン #define PowerPSW PIN_A7 // 赤色タクトスイッチ(主にブレットボードへの電力供給切換) #define OrPSW PIN_B0 // オレンジ色タクトスイッチ #define GrPSW PIN_B1 // 緑色タクトスイッチ #define BlPSW PIN_B2 // 青色タクトスイッチ #define YePSW PIN_B3 // 黄色タクトスイッチ // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // I2C LCD のアドレスと制御ライブラリのインクルード #define I2CLCD_ADDR 0x7C #include "I2C_LCD_AQM0802A_lib.c" // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // インクルードファイル #include // #include // #include // #include // #include // #include // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 大域変数の定義 int8 powerStatus = 0; // 現在の電力供給状態を示す変数 int8 blinkStatus = 0; // LED 点滅に使用する変数 int8 BlinkRedLED = 0; // 赤色LEDを点滅 int8 BlinkBlueLED= 0; // 青色LEDを点滅 int8 ick = 0; // この変数が1になったら計測値表示 int16 dataCount = 0; // 計測データ数(平均の計算に使用) int16 pushTimer = 0; // プッシュボタンを押している時間を計測 // float sAmp = 0.0; // 電流計測値の加算結果 float Amp = 0.0; // 平均電流計測値 float sVolt = 0.0; // 電圧計測値の加算結果 float Volt = 0.0; // 平均電圧計測値 // float AmpOffset = 0.0; // 出力電流ゼロ時の電流値(変換前) float AmpZero = 0.0; // 現在の電流値からの変化を表示するとき使用 // signed int8 mode = 0; // モード // 0:通常計測 // 1:変化量表示 // 2:遮断電流設定 // 3:使用電圧設定 // 4:温度表示 // 5:電流校正 // 6:電圧校正 signed int8 bMode = 0; // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // EEPROM に保存するデータの構造体 // struct _savedStatus { int check; float facAmp; // 電流変換係数 float facVolt; // 電圧変換係数 float limitAmp; // 遮断電流 int8 limitVolt; // 使用電圧(4~15V) }; struct _savedStatus par; // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 変換係数を EEPROM に保存する // void writeParameterToEEPROM() { int i; unsigned char *p; p = (unsigned char *)(&par); for(i=0;i2000) { BlinkRedLED = 1; BlinkBlueLED= 1; } } } ick = 1; return true; } } return false; } // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void ConvertData() { Amp = sAmp/(float)dataCount; if(powerStatus==0) AmpOffset = Amp; Amp = (Amp-AmpOffset)*par. facAmp; Volt= sVolt/(float)dataCount; Volt= Volt*par.facVolt; } // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // 表示 void ModeSelect() { I2C_lcd_gotoxy(0, 0); // 通常計測 if(mode==0){ ConvertData(); printf(I2C_LCD_putc,"%5.2f V",Volt); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc,"%6.3f A",Amp); } // 変化量表示 if(mode==1){ ConvertData(); if(buttonStatus(BlPSW,0)==true) AmpZero = Amp; if(buttonStatus(YePSW,0)==true) AmpZero = Amp; printf(I2C_LCD_putc,"N %4.0fmA", Amp*1000.0); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc,"D %4.0fmA", (Amp-AmpZero)*1000.0); } // 遮断電流設定 if(mode==2){ if(buttonStatus(BlPSW,0)==true){ par.limitAmp -= 0.01; } else if(buttonStatus(YePSW,0)==true){ par.limitAmp += 0.01; } printf(I2C_LCD_putc,"Set Amp "); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc,"%6.3f A", par.limitAmp); } // 使用電圧設定 if(mode==3){ if(buttonStatus(BlPSW,1)==true){ par.limitVolt -= 1; if(par.limitVolt<4) par.limitVolt = 5; } else if(buttonStatus(YePSW,1)==true){ par.limitVolt += 1; if(par.limitVolt>15) par.limitVolt = 15; } printf(I2C_LCD_putc,"Set Volt"); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc," %2d V", par.limitVolt); } // 温度表示 if(mode==4){ float temp; set_adc_channel(chTemp); delay_us(50); temp = ((float)read_adc()*3.3/1023.0-0.6)*100.0; printf(I2C_LCD_putc,"Temp. "); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc," %3.0f%cC",temp,0xDF); } // 電流校正 if(mode==5){ if(buttonStatus(BlPSW,0)==true){ par.facAmp -= 0.000003; } else if(buttonStatus(YePSW,0)==true){ par.facAmp += 0.000003; } ConvertData(); printf(I2C_LCD_putc,"Set fAmp"); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc,"%6.3f A", Amp); } // 電圧校正 if(mode==6){ if(buttonStatus(BlPSW,0)==true){ par.facVolt -= 0.00001; } else if(buttonStatus(YePSW,0)==true){ par.facVolt += 0.00001; } ConvertData(); printf(I2C_LCD_putc,"Set fVol"); I2C_lcd_gotoxy(0, 1); printf(I2C_LCD_putc,"%6.3f V",Volt); } } // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void setup_System() { setup_adc_ports(sAN0|sAN1|sAN3|VSS_VDD); setup_adc(ADC_CLOCK_DIV_16); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //32.7 ms overflow setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //262 ms overflow enable_interrupts(INT_RTCC); enable_interrupts(INT_TIMER1); enable_interrupts(GLOBAL); setup_oscillator(OSC_8MHZ|OSC_INTRC); port_B_pullups(0xFF); // init_I2CLCD(); // readParameterToEEPROM(); output_low(kPowerOut); output_low(kRedLED); output_high(kBlueLED); delay_ms(100); } // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void clear_parameter() { sAmp = sVolt = 0.0; dataCount = 0; } // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // void main() { setup_System(); // clear_parameter(); // while(true) { // モード切り替え if(buttonStatus(OrPSW,1)==true){ if(mode==0 && pushTimer>200){ mode = 5; } else { mode--; if(mode<0) mode = 4; } } else if(buttonStatus(GrPSW,1)==true){ if(mode==0 && pushTimer>200){ mode = 6; } else { mode++; if(mode>4) mode = 0; } } // パワースイッチが押されたとき // まだパワースイッチがオンになっていない場合にはボタンを離すまで待ってオンにする if(powerStatus==0){ if(buttonStatus(PowerPSW,1)==true){ powerStatus = 1; } } // パワースイッチがオンの状態では押した瞬間にオフにする。 else if(powerStatus==1){ if(buttonStatus(PowerPSW,0)==true) { powerStatus = 0; } } // 電圧電流異常で停止中の場合 else if(powerStatus>=2){ if(buttonStatus(PowerPSW,1)==true) { powerStatus = 0; } } // モードを切換えたときパラメータをEEPROMに書込む if(bMode!=mode) { if(!(bMode==0||bMode==1||bMode==4)) writeParameterToEEPROM(); bMode = mode; } // 実際にブレットボードへ電力を供給する制御を行う // powerStatus // 0 正常:電力供給停止中 // 1 正常:電力供給中 // 2 異常:異常電流による電力供給停止 // 3 異常:電圧異常による電力供給停止 switch(powerStatus){ case 1: output_high(kPowerOut); BlinkBlueLED = 1; BlinkRedLED = 0; // output_low(kBlueLED); output_low(kRedLED); break; case 2: output_low(kPowerOut); BlinkBlueLED = 0; BlinkRedLED = 0; output_low(kBlueLED); output_high(kRedLED); break; case 3: output_low(kPowerOut); BlinkBlueLED = 0; BlinkRedLED = 1; output_low(kBlueLED); break; default: output_low(kPowerOut); BlinkBlueLED = 0; BlinkRedLED = 0; output_high(kBlueLED); output_low(kRedLED); while(input(PowerPSW)==0); break; } // 計測値の表示 if(ick==1){ // 計測値の表示 ModeSelect(); // 加算パラメータをクリア clear_parameter(); ick = 0; } else { float tmp, nowAmp, nowVolt,limitVH,limitVL; set_adc_channel(chAmp); delay_us(50); tmp = (float)read_adc(); nowAmp = (tmp-AmpOffset)*par.facAmp;// 現在の瞬時電流計測値 sAmp += tmp; set_adc_channel(chVolt); delay_us(50); tmp = (float)read_adc(); nowVolt = tmp*par.facVolt; // 現在の瞬時電圧計測値 sVolt += tmp; dataCount++; // 給電状態の検出 limitVH = (float)par.limitVolt+0.5; limitVL = limitVH -1.0; if(nowAmp>par.limitAmp) powerStatus = 2; // 電流値が設定値を超えた else { int8 bPowerStatus = powerStatus; if(nowVolt>limitVH||nowVoltlimitVH) powerStatus = 3; // 電圧値が上限設定値を超えた // else if(nowVolt