Измерване с АЦП и управление на 7 сегментен индикатор
Използваме ESP32 devkit 1. На фигурата по-долу са показани изводите на модула.
Използван е седемсегментен индикатор (BA56-12SRWA) с общ анод. По този начин може да се реализира т.н. динамична индикация. Това означва, че в нито един момент не свети повече от една цифра от индикатора. Те се редуват, но с много голяма скорост, което не се забелязва от човешкото око.
С цел минимизиране на броя използвани пинове на модула използваме известния преместващ регистър 75HC595. За управление на анодите се използват PNP биполярни транзистори - консумацията е най-голяма когато свети цифра 8. Схемата на свързване е следната:
За свързване на индикатора се използват 6 извода от модула. Към аналогов вход е свързан потенциометър. Ето как са дефинирани изводите.
const int anodMSB = 13; const int anodMID = 33; const int anodLSB = 14; const int SER = 25; const int SRCLK = 26; const int RCLK = 27; const int adcPIN = 34;
Чрез таблица се конвертира число към сигнали, така че да светнат верните сегменти
const int Table[15]= // convert number to 7 segment {// GCXDEAFB 0b01011111, //0 0b01000001, //1 0b10011101, //2 0b11010101, //3 0b11000011, //4 0b11010110, //5 0b11011110, //6 0b01000101, //7 0b11011111, //8 0b11010111, //9 // 0b11001111, //A 0b11011010, //b 0b00011110, //c 0b10001111, //P 0b10000000 //- };
Задаваме чрез прекъсване от таймер опресняването на дисплея. Дефинираме таймер.
// interrupt timer hw_timer_t * timer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
А ето и целия код
const int anodMSB = 13; const int anodMID = 33; const int anodLSB = 14; const int SER = 25; const int SRCLK = 26; const int RCLK = 27; const int adcPIN = 34; volatile int adcValue; volatile int adcValueTmp; volatile int adcCntr; const int Table[15]= // convert number to 7 segment {// GCXDEAFB 0b01011111, //0 0b01000001, //1 0b10011101, //2 0b11010101, //3 0b11000011, //4 0b11010110, //5 0b11011110, //6 0b01000101, //7 0b11011111, //8 0b11010111, //9 // 0b11001111, //A 0b11011010, //b 0b00011110, //c 0b10001111, //P 0b10000000 //- }; volatile int Symbol[3]; volatile int Symbols_Cntr; volatile int point_pos; // interrupt timer hw_timer_t * timer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; //************************************************************************* // // //************************************************************************* void write_74HC595 (int val) { int i,j; j=0; val=255-val; i=0b10000000; do { if ((val&i)==0) {digitalWrite(SER,LOW);} else {digitalWrite(SER,HIGH);} // set data digitalWrite(SRCLK,HIGH);digitalWrite(SRCLK,LOW); // strobe i=i>>1; j++; }while(j<8); digitalWrite(RCLK,HIGH);digitalWrite(RCLK,LOW); } //************************************************************************* // // //************************************************************************* void Switch_OFF_Display (void) { digitalWrite(anodMSB,HIGH); digitalWrite(anodMID,HIGH); digitalWrite(anodLSB,HIGH); } //************************************************************************* // // //************************************************************************* int Refresh_Display (void) { int i; Switch_OFF_Display(); if (Symbols_Cntr==0) { i=Symbol[Symbols_Cntr]; if (point_pos==1) {i=i|0b00100000;} write_74HC595(i); digitalWrite(anodMSB,LOW);Symbols_Cntr++; return(0); } if (Symbols_Cntr==1) { i=Symbol[Symbols_Cntr]; if (point_pos==2) {i=i|0b00100000;} write_74HC595(i); digitalWrite(anodMID,LOW);Symbols_Cntr++; return(0); } if (Symbols_Cntr==2) { i=Symbol[Symbols_Cntr]; if (point_pos==3) {i=i|0b00100000;} write_74HC595(i); digitalWrite(anodLSB,LOW);Symbols_Cntr=0; return(0); } Symbols_Cntr=0; return(1); } //************************************************************************* // // //************************************************************************* void read_adc () { adcValueTmp = adcValueTmp+analogRead(adcPIN)+174; adcCntr++; if (adcCntr>=8) { adcCntr=0; adcValue=adcValueTmp/8; adcValueTmp=0; } } //************************************************************************* // // //************************************************************************* // timer ISR func void IRAM_ATTR onTimer() { portENTER_CRITICAL_ISR(&timerMux); Refresh_Display(); read_adc (); portEXIT_CRITICAL_ISR(&timerMux); } //************************************************************************* // // //************************************************************************* void find_digits (int Number) { int One,Ten,Hundred; Hundred=Number/100; Number=Number-(Hundred*100); Ten=Number/10; Number=Number-(Ten*10); One=Number; portENTER_CRITICAL(&timerMux); Symbol[0]=Table[Hundred]; Symbol[1]=Table[Ten]; Symbol[2]=Table[One]; portEXIT_CRITICAL(&timerMux); } //************************************************************************* // // //************************************************************************* void setup() { // put your setup code here, to run once: // set pin direction pinMode(anodMSB,OUTPUT); pinMode(anodMID,OUTPUT); pinMode(anodLSB,OUTPUT); pinMode(SER,OUTPUT); pinMode(SRCLK,OUTPUT); pinMode(RCLK,OUTPUT); // timer ISR timer = timerBegin(0, 80, true); // clock freq MHz timerAttachInterrupt(timer, &onTimer, true); timerAlarmWrite(timer, 1000, true); // in uS event clock timerAlarmEnable(timer); point_pos=1; } //************************************************************************* // // //************************************************************************* void loop() { delay(200); find_digits(adcValue/8); }
Коментари