Измерване с АЦП и управление на 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);
}

Коментари



Телефон: 0898 518 261
e-mail: info@ekits.eu
Адрес: София бул. Европа 177