Осциллограф на Arduino (LCD TFT 2.4″)

На базе Arduino UNO или NANO можно сделать простой осциллограф с минимальными функциями. В осциллографе применен дисплей LCD TFT 2,4 (SPFD5408). Максимальная частота сигнала которую можно фиксировать осциллографом 20000 Гц. Длительной развертки осциллографа можно менять от 0,1 до 20 мс. Максимальное напряжение подаваемое на вход осциллографа 5 В. Разрешение дисплея 320х240 точек.

Осциллограф имеет четыре режима работы:

  • Основной режим (доступен после включения осциллографа) — в основном режиме можно при помощи кнопок «+» и «-» менять разрешение развертки. Так же в нем применена автоматическая синхронизации по среднему уровню сигнала. В верхней части экрана можно видеть режим работы синхронизации (SYNC AUTO), длительность развертки, частоту сигнала и напряжения сигнала (максимальное, минимальное, амплитудное).
  • Ручная синхронизация (SYNC ADJ) — в режиме ручной синхронизации можно установить уровень напряжения входного сигнала при котором будет срабатывать синхронизация.
  • Режим паузы — режим паузы HOLD позволяет просматривать осциллограмму при помощи кнопок «+» и «-«. Для просмотра доступно 640 точек измерения.
  • Выбор входного напряжения — эта опция активируется при одновременном нажатии кнопок «+» и «-«, при этом вход осциллографа переключается в режим измерения с максимальным напряжением 1,1 В, этот режим обозначается на дисплее как «0.22V/DIV» (0.22 В/дел.). При повторном одновременном нажатии кнопок «+» и «-«, вход осциллографа переходит в основной режим измерения 1В/дел.(макс. 5 В) и на дисплее обозначается как «1.00V/DIV».

Основной режим

Ручная синхронизация

Режим HOLD

Подключение:

  • Дисплей LCD TFT 2,4 (SPFD5408) имеет 5 контактов шины синхронизации и 8 контактов для данных

TFT 2.4 — LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET // Arduino — A3, A2, A1, A0, A4

TFT 2.4 — D0, D1, D2, D3, D4, D5, D6, D7  // Arduino 8, 9, 2, 3, 4, 5, 6, 7

  • Кнопки управления

13   — menu

12  — плюс

10 — минус

  • Вход — можно использовать А7 (по умолчанию) или А5, входной сигнал необходимо подавать через резистор 4,7 кОм
  • Генератор — 11 цифровой выход используется как тестовый генератор. Частота ШИМ составляет приблизительно 490 Гц.

Библиотеки

Adafruit_GFX.zip

SPFD5408.zip

#include <Adafruit_GFX.h>    
#include <TftSpfd5408.h>
#include <SPI.h>
 
TftSpfd5408 tft(A3,A2,A1,A0,A4);/// LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET // A3,A2,A1,A0,A4
// D0 pin 8, D1 pin 9, D2 pin 2, D3 pin 3, D4 pin 4, D5 pin 5, D6 pin 6,D7 pin 7
void setup(){tft.reset();tft.begin(0x9341);Serial.begin(9600);
  tft.setRotation(1);tft.fillScreen(0x0000);tft.setTextColor(0xFFFF);tft.setTextSize(2); 
   analogWrite (11, 127); // PWM 9 ВЫХОД для тестирования осциллографа
   pinMode(13,INPUT);/// menu
   pinMode(12,INPUT);/// +
   pinMode(10,INPUT);/// -
   ADMUX  = 0b01100111;  // 0bxxxxx111 A7 nano // 0bxxxxx101 A5 uno // 0b01xxxxxx 5V // 0b11xxxxxx 1.1 V
   ADCSRA = 0b11100010;
}
 
int h0,sss=45,zz=20,x,y,i,i1,u,i2,i3,sinhro,sinhro1,kof;
int arr=0,arr1=255,menu,hold,hold_reg,raz=3;
float u_max,u_min=0,u_sig,per,f;
byte data[640],data1[640],w,w1;
unsigned long times,time,time1,time3;
 
void loop(){
  tft.setTextColor(0xFFFF);tft.setRotation(1);tft.setTextSize(1);
  tft.setCursor(140,20);tft.print(" RCL-RADIO.RU ");
  tft.setCursor(0, 0);
 
///////////////////////////// кнопки управления /////////////////////
  if(digitalRead(13)==HIGH){menu++;tft.fillRect(0, 0, 120, 20, 0x0000);
   tft.fillRect(0, 40, 10, 200, 0x0000);}if(menu>2){tft.fillScreen(0x0000);menu=0;}
  if(menu==2){hold=1;}else{hold=0;hold_reg=0;}
 
  if(menu==0){
    if(digitalRead(12)==HIGH){raz++;tft.fillRect(120, 0, 110, 20, 0x0000);tft.fillRect(0, 40, 320, 220, 0x0000);}
    if(digitalRead(10)==HIGH){raz--;tft.fillRect(120, 0, 110, 20, 0x0000);tft.fillRect(0, 40, 320, 220, 0x0000);}
    if(raz>7){raz=7;}if(raz<0){raz=0;}
  switch(raz){  
   case 0: zz=1;  kof=2; per=0.1;break;
   case 1: zz=1;  kof=1; per=0.2;break;
   case 2: zz=7;  kof=1; per=0.5;break;
   case 3: zz=17; kof=1; per=1;  break;
   case 4: zz=36; kof=1; per=2;  break;
   case 5: zz=95; kof=1; per=5;  break;
   case 6: zz=185;kof=1; per=10; break;
   case 7: zz=380;kof=1; per=20; break;
}}
 
  if(menu==1){ // ручная синхронизация
    if(digitalRead(12)==HIGH){sss+=5;}
    if(digitalRead(10)==HIGH){sss-=5;}
    if(sss>240){sss=240;}if(sss<20){sss=20;}}
 
  if(menu==2){ // кнопки в режиме HOLD
    if(digitalRead(12)==HIGH){hold_reg+=5;}
    if(digitalRead(10)==HIGH){hold_reg-=5;}
    if(hold_reg>319){hold_reg=319;} if(hold_reg<0){hold_reg=0;}}
 
  if(digitalRead(12)==HIGH&&digitalRead(10)==HIGH){w++;w1=1; tft.fillScreen(0x0000);if(w>1){w=0;}}
    if(w==0&&w1==1){ADMUX  = 0b01100111;w1=0;}
    if(w==1&&w1==1){ADMUX  = 0b11100111;w1=0;}
 
//////////////////////////////// измерение и синхронизация //////////////////////
  if(hold==0){
  ADS();while(ADCH!=sinhro){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0; // ждем минимальной амплитуды
  ADS();while(ADCH<sss){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0;// СИНХРОНИЗАЦИЯ
  times=micros();
  while(i<639){i++;
   delayMicroseconds(zz);
   ADS();data[i]=ADCH; // ИЗМЕРЕНИЕ 
   }i=0;times=micros()-times;
  Serial.println(times); // монитор порта время измерения 640 точек 
  }
////////////////////////////////////////////////////////////////////////////////
 
/////////////////////////////ВЕРХНЯЯ ЧАСТЬ ЭКРАНА //////////////////////////////
//////////////////// максимальное и минимальное напряжение //////////// 
  if(millis()-time>1000&&hold==0){
    while(i<319){i++;arr = max(arr,data[i]);arr1=min(arr1,data[i]);}i=0;sinhro1=arr;sinhro=arr1;
     tft.setCursor(250,0);tft.setTextSize(1);tft.fillRect(280, 0, 25, 30, 0x0000);tft.fillRect(60, 15, 80, 20, 0x0000);
     if(w==0){u_max=arr*5.0/255;u_min=arr1*5.0/255;}else{u_max=arr*1.1/255;u_min=arr1*1.1/255;}
     tft.setTextColor(0xFFFF);tft.print("Umax=");tft.print(u_max);tft.print(" V ");
     tft.setCursor(250,10);
     tft.setTextColor(0xFFFF);tft.print("Umin=");tft.print(u_min);tft.print(" V ");
     tft.setCursor(250,20);
     tft.setTextColor(0xFFFF);tft.print("Usig=");tft.print(u_sig=u_max-u_min);tft.print(" V ");
     if(menu!=1){sss=(sinhro1-sinhro)/2;} /// средний уровень напряжения для автосинхронизации
     arr=0;arr1=255;
    ///// частотомер от 315 Гц//////  
    ADS();while(ADCH>sss-10){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0;
    ADS();while(ADCH<sss+10){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0;time3=micros();
    ADS();while(ADCH>sss-10){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0;
    ADS();while(ADCH<sss+10){ADS();ADCH;h0++;if(h0>10000){break;}}h0=0;f=micros()-time3;
     f=(1/f)*1000;
     tft.setTextSize(1);tft.setCursor(0,20);if(w==0){tft.print("1.00V/DIV ");}else{tft.print("0.22V/DIV ");}
     tft.print(" F=");tft.print(f,3);tft.print(" kHz ");
 
     time=millis();}i=0;
     /// вывод HOLD, длительность развертки, синхронизация и частота
     tft.setCursor(0,0);
     if(hold==1){tft.setTextSize(2);tft.setTextColor(0xFFFF);tft.print("HOLD     ");}
     if(menu==0){tft.setTextSize(2);tft.setTextColor(0xFFFF);tft.print("SYNC AUTO");
     tft.print("   ");tft.print(per,1);tft.println(" mS");}
     if(menu==1){tft.setTextSize(2);tft.setTextColor(0xFFFF);tft.print("SYNC ADJ ");}
/////////////////////////////////////////////////////////////////////////////////   
     setka();
///////////////////////////// вывод сигнала //////////////////////////////////// 
  while(i<639){i++;if(hold==0){data[i]=data[i]/1.29;}}i=0;// поправка на размер экрана int 255 > int 240
  while(i<319){i++; /// основной цикл вывода изображения на экран
    tft.drawLine(i*kof,239-data1[i],i*kof,239-data1[i-1],0x0000);// стирание сигнала
   if(i<2){}else{tft.drawLine(i*kof,239-data[i+hold_reg],i*kof,239-data[i-1+hold_reg],0xF800);}}i=0;// вывод сигнала
  while(i<319){i++;data1[i]=data[i+hold_reg];}i=0; // массив под стирание
////////////////////////////////////////////////////////////////////////////////
 
}// LOOP
 
void setka(){ ///// сетка 
 
  if(menu==1){ //////////// метка ручной синхронизации
    tft.drawFastHLine(0,240-(sss-5)/1.27,10, 0x0000);tft.drawFastHLine(0,240-sss/1.27,10, 0x07ff);tft.drawFastHLine(0,240-(sss+5)/1.27,10, 0x0000);}
  if(hold==1){ //////////// метка прокрутки осциллограммы в режиме HOLD
    tft.drawFastHLine(hold_reg-10,30,10, 0x0000);tft.drawFastHLine(hold_reg,30,10, 0x07ff);tft.drawFastHLine(hold_reg+10,30,10, 0x0000);
    tft.drawFastHLine(hold_reg-10,31,10, 0x0000);tft.drawFastHLine(hold_reg,31,10, 0x07ff);tft.drawFastHLine(hold_reg+10,31,10, 0x0000);}
 
  for(y=40;y<240;y=y+40){
  for(x=10;x<320;x=x+10){
tft.drawPixel(x, y, 0xCDCD);}}
 
  for(x=52;x<320;x=x+52){
  for(y=40;y<240;y=y+10){
tft.drawPixel(x, y, 0xCDCD);}}}
 
void ADS(){while ((ADCSRA & 0x10)==0);ADCSRA|=0x10;}

Comments

  1. Интересное решение, иногда надо просто просмотреть сигнал. Собрал, загрузил скетч, но как-то странно работает, непрерывно меняются на экране SYNC AVTO, SYNC ADJI, HOLD.Кто подскажет, что не так.

Добавить комментарий

Войти с помощью: