Текущее время: 19 мар 2024, 09:47

Калининград & ХОББИ

Занятие любимым хобби - это путь к счастливой жизни!

Осциллограф на Ардуино

Тут собраны схемы различных устройств сделанных на контроллерах Ардуино, Лазерный гравер на Ардуино, Металлоискатель на Ардуино, Метеостанция, Кодовый замок, и множество других устройств и изобретений
Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 10:39

Всем здрасти :)

У меня возникла острая необходимость в измерительном приборе - осциллографе , а покупать его не было средств, так как данные приборы достаточно дорого стоят - цены на цифровые осциллографы с цветными дисплеями начинаются от 30 000 руб.

Я решил сделать самодельный осциллограф на Ардуино УНО и платой расширения Ардуино TFT LCD шилд с чипом
ST7781 240x320 ID=0x7783

В этой теме буду освещать ход разработки и выкладывать схемы, скетчи, библиотеки , ну и конечно же фотографии хода разработки.



Вложения
220-thickbox_default.jpg
219-thickbox_default.jpg
212-thickbox_default.jpg

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 10:47

Для создания осциллографа нам понадобится еще
Библиотека для графического дисплея Ардуино TFT LCD шилд

Скетч и библиотеки работают в версии Arduino IDE 1.5.7
которую нужно скачать тут
https://drive.google.com/open?id=1AKu5w ... R2cHC3H8Yo

Скетч осциллографа на Ардуино

Код: выделить все
/*
* ARDUINOSCOPE - v.1.1
 */

#include "TFTLCD.h"

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

#define txtLINE0   0
#define txtLINE1   16
#define txtLINE2   30
#define txtLINE3   46

const int LCD_WIDTH = 320;
const int LCD_HEIGHT = 240;
const int SAMPLES = 270;
const int DOTS_DIV = 30;


int sensorValue = 0;
const int ad_sw =  3;                    // Analog 3 pin for switches
const int ad_ch0 = 4;                   // Analog 4 pin for channel 0
const int ad_ch1 = 5;                   // Analog 5 pin for channel 1
const unsigned long VREF[] = {150, 300, 750, 1500, 3000}; // reference voltage 5.0V ->  150 :   1V/div range (100mV/dot)
                                        // It means 5.0 * DOTS_DIV = 150. Use 4.9 if reference voltage is 4.9[V]
                                        //                        -> 300 : 0.5V/div
                                        //                        -> 750 : 0.2V/div
                                        //                        ->1500 : 100mV/div
                                        //                       -> 3000 :  50mV/div
const int MILLIVOL_per_dot[] = {33, 17, 6, 3, 2}; // mV/dot
const int MODE_ON = 0;
const int MODE_INV = 1;
const int MODE_OFF = 2;
const char *Modes[] = {" NORM", " INV", " OFF"};
const int TRIG_AUTO = 0;
const int TRIG_NORM = 1;
const int TRIG_SCAN = 2;
const int TRIG_ONE  = 3;
const char *TRIG_Modes[] = {" Auto", " Norm", " Scan", " One"};
const int TRIG_E_UP = 0;
const int TRIG_E_DN = 1;
#define RATE_MIN 0
#define RATE_MAX 13
const char *Rates[] = {"F1-1", "F1-2 ", "F2  ", "5ms", "10ms", "20ms", "50ms", "0.1s", "0.2s", "0.5s", "1s", "2s", "5s", "10s"};
#define RANGE_MIN 0
#define RANGE_MAX 4
const char *Ranges[] = {"1V ", "0.5V", "0.2V", "0.1V", "50mV"};
unsigned long startMillis;
byte data[4][SAMPLES];                   // keep twice of the number of channels to make it a double buffer
byte sample=0;                           // index for double buffer

///////////////////////////////////////////////////////////////////////////////////////////////
// Define colors here
#define   BGCOLOR  BLACK
#define   GRIDCOLOR BLUE
#define CH1COLOR  BLUE
#define CH2COLOR  GREEN

// Declare variables and set defaults here
// Note: only ch1 is available with Aitendo's parallel 320x240 TFT LCD 
byte range0 = RANGE_MIN, ch0_mode = MODE_OFF;  // CH0 включение выключение канала MODE_OFF
short ch0_off = 204;
byte range1 = RANGE_MIN, ch1_mode = MODE_ON;  // CH1
short ch1_off = 204;
byte rate = 3;         // sampling rate 3
byte trig_mode = TRIG_AUTO, trig_lv = 30, trig_edge = TRIG_E_UP, trig_ch = 1; // trigger settings
byte Start = 1;  // Start sampling 1
byte menu = 0;  // Default menu
///////////////////////////////////////////////////////////////////////////////////////////////

void setup(){
  tft.reset();
  tft.initDisplay();
  tft.setRotation(3);

  tft.fillScreen(BGCOLOR);
   

  DrawGrid();
  DrawText();
}

void CheckSW() {
  static unsigned long Millis = 0, oMillis = 0;
  unsigned long ms;
  unsigned short ain = analogRead(ad_sw);
 //Serial.println(ain);
  return;
  ms = millis();
  if ((ms - Millis)<5)
  return;
  Millis = ms;
  oMillis = Millis;

 
   //Serial.println(ain);
  DrawText();
}

void menu0_sw(int sw) { 
  switch (sw) {
   case 0:
    // START/HOLD
    if (Start)
       Start = 0;
     else
       Start = 1;
    break;
   case 1:
    // CH0 RANGE -
    if (range0 < RANGE_MAX)
      range0 ++;
    break;
   case 2:
    // CH1 RANGE -
    if (range1 < RANGE_MAX)
      range1 ++;
    break;
   case 3:
    // RATE FAST
    if (rate > 0)
      rate --;
    break;
   case 4:
    // TRIG MODE
    if (trig_mode < TRIG_ONE)
      trig_mode ++;
    else
      trig_mode = 0;
    break;
   case 5:
    // SEND
    SendData();
    break;
   case 6:
    // TRIG MODE
    if (trig_mode > 0)
      trig_mode --;
    else
      trig_mode = TRIG_ONE;
    break;
   case 7:
    // RATE SLOW
    if (rate < RATE_MAX)
      rate ++;
    break;
   case 8:
    // CH1 RANGE +
    if (range1 > 0)
      range1 --;
    break;
   case 9:
    // CH0 RANGE +
    if (range0 > 0)
      range0 --;
    break;
   case 10:
   default:
    // MENU SW
    menu ++;
     break;
  }
}



void SendData() {
  Serial.print(Rates[rate]);
  Serial.println("/div (30 samples)");
  for (int i=0; i<SAMPLES; i ++) {
      Serial.print(data[sample + 0][i]*MILLIVOL_per_dot[range0]);
      Serial.print(" ");
      Serial.println(data[sample + 1][i]*MILLIVOL_per_dot[range1]);
   }
}

void DrawGrid() {
    for (int x=0; x<=SAMPLES; x += 2) { // Horizontal Line
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
      if (LCD_HEIGHT == 240)
        tft.drawPixel(x, LCD_HEIGHT-1, GRIDCOLOR);
    }
    for (int x=0; x<=SAMPLES; x += DOTS_DIV ) { // Vertical Line
      for (int y=0; y<=LCD_HEIGHT; y += 2) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
    }
}

void DrawText() {
  tft.setTextColor(YELLOW);
  tft.setTextSize(1);
  tft.setCursor(SAMPLES+3, 20);
  tft.print(Ranges[range1]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 30);
  tft.print(Rates[rate]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 40);
  tft.println(TRIG_Modes[trig_mode]);
  tft.setCursor(SAMPLES+3, 50);
  tft.println(trig_edge == TRIG_E_UP ? " UP" : " DN");
  tft.setCursor(SAMPLES+3, 60);
  tft.println(Modes[ch1_mode]);
  tft.setTextColor(MAGENTA);
  tft.println("");
   tft.setCursor(SAMPLES+3, 90);
  tft.println(" 1 ");
  tft.println("");
   tft.setCursor(SAMPLES+3, 120);
  tft.println(" 2 ");
  tft.println("");
   tft.setCursor(SAMPLES+3, 150);
  tft.println(" 3 ");
  tft.println("");
  tft.setCursor(SAMPLES+3, 180);
  tft.println(" 4 ");
  tft.println("");
  tft.setCursor(SAMPLES+3, 210);
  tft.println(" 5 ");
//  tft.setCursor(SAMPLES, 70);
//  tft.println(trig_ch == 0 ? "T:1" : "T:2");

}

void DrawGrid(int x) {
    if ((x % 2) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV)
        tft.drawPixel(x, y, GRIDCOLOR);
    if ((x % DOTS_DIV) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += 2)
        tft.drawPixel(x, y, GRIDCOLOR);
}

void ClearAndDrawGraph() {
  int clear = 0;
 
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
   for (int x=0; x<(SAMPLES-1); x++) {
     tft.drawLine(x, LCD_HEIGHT-data[clear+0][x], x+1, LCD_HEIGHT-data[clear+0][x+1], BGCOLOR);
     tft.drawLine(x, LCD_HEIGHT-data[clear+1][x], x+1, LCD_HEIGHT-data[clear+1][x+1], BGCOLOR);
     if (ch0_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+0][x], x+1, LCD_HEIGHT-data[sample+0][x+1], CH1COLOR);
     if (ch1_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+1][x], x+1, LCD_HEIGHT-data[sample+1][x+1], CH2COLOR);
     CheckSW();
  } 
#endif
}

void ClearAndDrawDot(int i) {
  int clear = 0;

  if (i <= 1)
    return;
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+0][i-1], i, LCD_HEIGHT-data[clear+0][i], BGCOLOR);
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+1][i-1], i, LCD_HEIGHT-data[clear+1][i], BGCOLOR);
  if (ch0_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+0][i-1], i, LCD_HEIGHT-data[sample+0][i], CH1COLOR);
  if (ch1_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+1][i-1], i, LCD_HEIGHT-data[sample+1][i], CH2COLOR);
#endif
  DrawGrid(i);
}

void DrawGraph() {
   for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[sample+0][x], CH1COLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[sample+1][x], CH2COLOR);
  }
}

void ClearGraph() {
  int clear = 0;
 
  if (sample == 0)
    clear = 2;
  for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[clear+0][x], BGCOLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[clear+1][x], BGCOLOR);
  }
}

inline unsigned long adRead(byte ch, byte mode, int off)
{
  unsigned long a = analogRead(ch);
  a = ((a+off)*VREF[ch == ad_ch0 ? range0 : range1]+512) >> 10;
  a = a>=(LCD_HEIGHT+1) ? LCD_HEIGHT : a;
  if (mode == MODE_INV)
    return LCD_HEIGHT - a;
  return a;
}

void  loop() {
   
 
  if (trig_mode != TRIG_SCAN) {
      unsigned long st = millis();
      byte oad;
      if (trig_ch == 0)
        oad = adRead(ad_ch0, ch0_mode, ch0_off);
      else
        oad = adRead(ad_ch1, ch1_mode, ch1_off);
      for (;;) {
        byte ad;
        if (trig_ch == 0)
          ad = adRead(ad_ch0, ch0_mode, ch0_off);
        else
          ad = adRead(ad_ch1, ch1_mode, ch1_off);

        if (trig_edge == TRIG_E_UP) {
           if (ad >= trig_lv && ad > oad)
           //Serial.println(1);
            break;
        } else {
           if (ad <= trig_lv && ad < oad)
         
            break;
        }
        oad = ad;
       
     
        CheckSW();
     
        if (trig_mode == TRIG_SCAN)
          break;
        if (trig_mode == TRIG_AUTO && (millis() - st) > 100)
          break;
      }
  }
 
  // sample and draw depending on the sampling rate
    if (rate <= 5 && Start) {
    // change the index for the double buffer
    if (sample == 0)
      sample = 2;
    else
      sample = 0;

    if (rate == 0) { // full speed, channel 0 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+1][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 1) { // full speed, channel 1 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+0][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 2) { // full speed, dual channel
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st);
    } else if (rate >= 3 && rate <= 5) { // .5ms, 1ms or 2ms sampling
      const unsigned long r_[] = {5000/DOTS_DIV, 10000/DOTS_DIV, 20000/DOTS_DIV};
      unsigned long st0 = millis();
      unsigned long st = micros();
      unsigned long r = r_[rate - 3];
      for (int i=0; i<SAMPLES; i ++) {
        while((st - micros())<r) ;
        st += r;
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st0);
    }
    ClearAndDrawGraph();
    CheckSW();
    DrawGrid();
    DrawText();
  } else if (Start) { // 5ms - 500ms sampling
  // copy currently showing data to another
    if (sample == 0) {
      for (int i=0; i<SAMPLES; i ++) {
        data[2][i] = data[0][i];
        data[3][i] = data[1][i];
      }
    } else {
      for (int i=0; i<SAMPLES; i ++) {
        data[0][i] = data[2][i];
        data[1][i] = data[3][i];
      }     
    }

    const unsigned long r_[] = {50000/DOTS_DIV, 100000/DOTS_DIV, 200000/DOTS_DIV,
                      500000/DOTS_DIV, 1000000/DOTS_DIV, 2000000/DOTS_DIV,
                      5000000/DOTS_DIV, 10000000/DOTS_DIV};
    unsigned long st0 = millis();
    unsigned long st = micros();
    for (int i=0; i<SAMPLES; i ++) {
      while((st - micros())<r_[rate-6]) {
        CheckSW();
        if (rate<6)
          break;
      }
      if (rate<6) { // sampling rate has been changed
        tft.fillScreen(BGCOLOR);
        break;
      }
      st += r_[rate-6];
      if (st - micros()>r_[rate-6])
          st = micros(); // sampling rate has been changed to shorter interval
      if (!Start) {
         i --;
         continue;
      }
      data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      ClearAndDrawDot(i);     
    }
    // Serial.println(millis()-st0);
    DrawGrid();
    DrawText();
  } else {
    CheckSW();
  }
  if (trig_mode == TRIG_ONE)
    Start = 0;
   
}



Вложения
Adafruit_GFX.zip
Adafruit_GFX.h
(22.05 KiB) Скачиваний: 3470
TFTLCD.rar
Осциллограф на Ардуино УНО
(111 KiB) Скачиваний: 6133

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 11:07

Идем далее.

Подключаем к Ардуино ИДЕ библиотеку для управления графическим дисплеем , копируем скетч осциллографа и проверяем его в работе :)

Скетч осциллографа на Ардуино:
я взял его на каком то японском сайте, без описаний, ну и сыроват он немного, но главное что он работает !

Код: выделить все
/*
 * Arduino Oscilloscope using a graphic LCD
 */

#include "TFTLCD.h"

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

// #include <Arial14.h>  // font definitions

#define txtLINE0   0
#define txtLINE1   16
#define txtLINE2   30
#define txtLINE3   46

const int LCD_WIDTH = 320;
const int LCD_HEIGHT = 240;
const int SAMPLES = 270;
const int DOTS_DIV = 30;


int sensorValue = 0;
const int ad_sw = A3;                    // Analog 3 pin for switches
const int ad_ch0 = 4;                   // Analog 4 pin for channel 0
const int ad_ch1 = 5;                   // Analog 5 pin for channel 1
const unsigned long VREF[] = {150, 300, 750, 1500, 3000}; // reference voltage 5.0V ->  150 :   1V/div range (100mV/dot)
                                        // It means 5.0 * DOTS_DIV = 150. Use 4.9 if reference voltage is 4.9[V]
                                        //                        -> 300 : 0.5V/div
                                        //                        -> 750 : 0.2V/div
                                        //                        ->1500 : 100mV/div
                                        //                       -> 3000 :  50mV/div
const int MILLIVOL_per_dot[] = {33, 17, 6, 3, 2}; // mV/dot
const int MODE_ON = 0;
const int MODE_INV = 1;
const int MODE_OFF = 2;
const char *Modes[] = {" NORM", " INV", " OFF"};
const int TRIG_AUTO = 0;
const int TRIG_NORM = 1;
const int TRIG_SCAN = 2;
const int TRIG_ONE  = 3;
const char *TRIG_Modes[] = {" Auto", " Norm", " Scan", " One"};
const int TRIG_E_UP = 0;
const int TRIG_E_DN = 1;
#define RATE_MIN 0
#define RATE_MAX 13
const char *Rates[] = {"F1-1", "F1-2 ", "F2  ", "5ms", "10ms", "20ms", "50ms", "0.1s", "0.2s", "0.5s", "1s", "2s", "5s", "10s"};
#define RANGE_MIN 0
#define RANGE_MAX 4
const char *Ranges[] = {"1V ", "0.5V", "0.2V", "0.1V", "50mV"};
unsigned long startMillis;
byte data[4][SAMPLES];                   // keep twice of the number of channels to make it a double buffer
byte sample=0;                           // index for double buffer

///////////////////////////////////////////////////////////////////////////////////////////////
// Define colors here
#define   BGCOLOR  BLACK
#define   GRIDCOLOR WHITE
#define CH1COLOR  BLUE
#define CH2COLOR  GREEN

// Declare variables and set defaults here
// Note: only ch1 is available with Aitendo's parallel 320x240 TFT LCD 
byte range0 = RANGE_MIN, ch0_mode = MODE_OFF;  // CH0
short ch0_off = 204;
byte range1 = RANGE_MIN, ch1_mode = MODE_ON;  // CH1
short ch1_off = 204;
byte rate = 3;                                // sampling rate
byte trig_mode = TRIG_AUTO, trig_lv = 30, trig_edge = TRIG_E_UP, trig_ch = 1; // trigger settings
byte Start = 1;  // Start sampling
byte menu = 0;  // Default menu
///////////////////////////////////////////////////////////////////////////////////////////////

void setup(){
  tft.reset();
  tft.initDisplay();
  tft.setRotation(3);

  tft.fillScreen(BGCOLOR);

  tft.setTextColor(WHITE);
  tft.setTextSize(1);
  tft.setCursor(75, 100);
  tft.print("Arduino OscilloScope");
  tft.setCursor(75, 120);
  tft.print(" 2 CHANNEL ");
  tft.setCursor(75, 140);
  tft.print("(c) NEWMAR.RU  - 2015. ");
  delay(2000);

  tft.fillScreen(BGCOLOR);
   
  Serial.begin(9600);
  DrawGrid();
  DrawText();
}

void CheckSW() {
  static unsigned long Millis = 0, oMillis = 0;
  unsigned long ms;
  unsigned short ain = analogRead(ad_sw);
 //Serial.println(ain);
  return;
  ms = millis();
  if ((ms - Millis)<5)
  return;
  Millis = ms;
  oMillis = Millis;
   //Serial.println(ain);
  DrawText();
}

void menu0_sw(int sw) { 
  switch (sw) {
   case 0:
    // START/HOLD
    if (Start)
       Start = 0;
     else
       Start = 1;
    break;
   case 1:
    // CH0 RANGE -
    if (range0 < RANGE_MAX)
      range0 ++;
    break;
   case 2:
    // CH1 RANGE -
    if (range1 < RANGE_MAX)
      range1 ++;
    break;
   case 3:
    // RATE FAST
    if (rate > 0)
      rate --;
    break;
   case 4:
    // TRIG MODE
    if (trig_mode < TRIG_ONE)
      trig_mode ++;
    else
      trig_mode = 0;
    break;
   case 5:
    // SEND
    SendData();
    break;
   case 6:
    // TRIG MODE
    if (trig_mode > 0)
      trig_mode --;
    else
      trig_mode = TRIG_ONE;
    break;
   case 7:
    // RATE SLOW
    if (rate < RATE_MAX)
      rate ++;
    break;
   case 8:
    // CH1 RANGE +
    if (range1 > 0)
      range1 --;
    break;
   case 9:
    // CH0 RANGE +
    if (range0 > 0)
      range0 --;
    break;
   case 10:
   default:
    // MENU SW
    menu ++;
     break;
  }
}



void SendData() {
  Serial.print(Rates[rate]);
  Serial.println("/div (30 samples)");
  for (int i=0; i<SAMPLES; i ++) {
      Serial.print(data[sample + 0][i]*MILLIVOL_per_dot[range0]);
      Serial.print(" ");
      Serial.println(data[sample + 1][i]*MILLIVOL_per_dot[range1]);
   }
}

void DrawGrid() {
    for (int x=0; x<=SAMPLES; x += 2) { // Horizontal Line
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
      if (LCD_HEIGHT == 240)
        tft.drawPixel(x, LCD_HEIGHT-1, GRIDCOLOR);
    }
    for (int x=0; x<=SAMPLES; x += DOTS_DIV ) { // Vertical Line
      for (int y=0; y<=LCD_HEIGHT; y += 2) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
    }
}

void DrawText() {
  tft.setTextColor(YELLOW);
  tft.setTextSize(1);
  tft.setCursor(SAMPLES+3, 20);
  tft.print(Ranges[range1]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 30);
  tft.print(Rates[rate]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 40);
  tft.println(TRIG_Modes[trig_mode]);
  tft.setCursor(SAMPLES+3, 50);
  tft.println(trig_edge == TRIG_E_UP ? "UP" : "DN");
  tft.setCursor(SAMPLES+3, 60);
  tft.println(Modes[ch1_mode]);
  tft.setTextColor(RED);
  tft.println("");
   tft.setCursor(SAMPLES+3, 90);
  tft.println(" 1 V");
  tft.println("");
   tft.setCursor(SAMPLES+3, 120);
  tft.println(" 2 V");
  tft.println("");
   tft.setCursor(SAMPLES+3, 150);
  tft.println(" 3 V");
  tft.println("");
  tft.setCursor(SAMPLES+3, 180);
  tft.println(" 4 V");
  tft.println("");
  tft.setCursor(SAMPLES+3, 210);
  tft.println(" 5 V");
//  tft.setCursor(SAMPLES, 70);
//  tft.println(trig_ch == 0 ? "T:1" : "T:2");

}

void DrawGrid(int x) {
    if ((x % 2) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV)
        tft.drawPixel(x, y, GRIDCOLOR);
    if ((x % DOTS_DIV) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += 2)
        tft.drawPixel(x, y, GRIDCOLOR);
}

void ClearAndDrawGraph() {
  int clear = 0;
 
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
   for (int x=0; x<(SAMPLES-1); x++) {
     tft.drawLine(x, LCD_HEIGHT-data[clear+0][x], x+1, LCD_HEIGHT-data[clear+0][x+1], BGCOLOR);
     tft.drawLine(x, LCD_HEIGHT-data[clear+1][x], x+1, LCD_HEIGHT-data[clear+1][x+1], BGCOLOR);
     if (ch0_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+0][x], x+1, LCD_HEIGHT-data[sample+0][x+1], CH1COLOR);
     if (ch1_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+1][x], x+1, LCD_HEIGHT-data[sample+1][x+1], CH2COLOR);
     CheckSW();
  } 
#endif
}

void ClearAndDrawDot(int i) {
  int clear = 0;

  if (i <= 1)
    return;
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+0][i-1], i, LCD_HEIGHT-data[clear+0][i], BGCOLOR);
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+1][i-1], i, LCD_HEIGHT-data[clear+1][i], BGCOLOR);
  if (ch0_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+0][i-1], i, LCD_HEIGHT-data[sample+0][i], CH1COLOR);
  if (ch1_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+1][i-1], i, LCD_HEIGHT-data[sample+1][i], CH2COLOR);
#endif
  DrawGrid(i);
}

void DrawGraph() {
   for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[sample+0][x], CH1COLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[sample+1][x], CH2COLOR);
  }
}

void ClearGraph() {
  int clear = 0;
 
  if (sample == 0)
    clear = 2;
  for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[clear+0][x], BGCOLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[clear+1][x], BGCOLOR);
  }
}

inline unsigned long adRead(byte ch, byte mode, int off)
{
  unsigned long a = analogRead(ch);
  a = ((a+off)*VREF[ch == ad_ch0 ? range0 : range1]+512) >> 10;
  a = a>=(LCD_HEIGHT+1) ? LCD_HEIGHT : a;
  if (mode == MODE_INV)
    return LCD_HEIGHT - a;
  return a;
}

void  loop() {
   
 
  if (trig_mode != TRIG_SCAN) {
      unsigned long st = millis();
      byte oad;
      if (trig_ch == 0)
        oad = adRead(ad_ch0, ch0_mode, ch0_off);
      else
        oad = adRead(ad_ch1, ch1_mode, ch1_off);
      for (;;) {
        byte ad;
        if (trig_ch == 0)
          ad = adRead(ad_ch0, ch0_mode, ch0_off);
        else
          ad = adRead(ad_ch1, ch1_mode, ch1_off);

        if (trig_edge == TRIG_E_UP) {
           if (ad >= trig_lv && ad > oad)
            break;
        } else {
           if (ad <= trig_lv && ad < oad)
            break;
        }
        oad = ad;
       
     
        CheckSW();
     
        if (trig_mode == TRIG_SCAN)
          break;
        if (trig_mode == TRIG_AUTO && (millis() - st) > 100)
          break;
      }
  }
 
  // sample and draw depending on the sampling rate
    if (rate <= 5 && Start) {
    // change the index for the double buffer
    if (sample == 0)
      sample = 2;
    else
      sample = 0;

    if (rate == 0) { // full speed, channel 0 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+1][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 1) { // full speed, channel 1 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+0][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 2) { // full speed, dual channel
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st);
    } else if (rate >= 3 && rate <= 5) { // .5ms, 1ms or 2ms sampling
      const unsigned long r_[] = {5000/DOTS_DIV, 10000/DOTS_DIV, 20000/DOTS_DIV};
      unsigned long st0 = millis();
      unsigned long st = micros();
      unsigned long r = r_[rate - 3];
      for (int i=0; i<SAMPLES; i ++) {
        while((st - micros())<r) ;
        st += r;
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st0);
    }
    ClearAndDrawGraph();
    CheckSW();
    DrawGrid();
    DrawText();
  } else if (Start) { // 5ms - 500ms sampling
  // copy currently showing data to another
    if (sample == 0) {
      for (int i=0; i<SAMPLES; i ++) {
        data[2][i] = data[0][i];
        data[3][i] = data[1][i];
      }
    } else {
      for (int i=0; i<SAMPLES; i ++) {
        data[0][i] = data[2][i];
        data[1][i] = data[3][i];
      }     
    }

    const unsigned long r_[] = {50000/DOTS_DIV, 100000/DOTS_DIV, 200000/DOTS_DIV,
                      500000/DOTS_DIV, 1000000/DOTS_DIV, 2000000/DOTS_DIV,
                      5000000/DOTS_DIV, 10000000/DOTS_DIV};
    unsigned long st0 = millis();
    unsigned long st = micros();
    for (int i=0; i<SAMPLES; i ++) {
      while((st - micros())<r_[rate-6]) {
        CheckSW();
        if (rate<6)
          break;
      }
      if (rate<6) { // sampling rate has been changed
        tft.fillScreen(BGCOLOR);
        break;
      }
      st += r_[rate-6];
      if (st - micros()>r_[rate-6])
          st = micros(); // sampling rate has been changed to shorter interval
      if (!Start) {
         i --;
         continue;
      }
      data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      ClearAndDrawDot(i);     
    }
    // Serial.println(millis()-st0);
    DrawGrid();
    DrawText();
  } else {
    CheckSW();
  }
  if (trig_mode == TRIG_ONE)
    Start = 0;
   
}



Вложения
7.jpg
Arduinoscope
6.jpg
самодельный осциллограф
5.JPG
Осциллограф на Ардуино

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 11:19

Для нашего будущего осциллографа на Ардуино нам понадобится еще изготовить корпус.

Перебрав все возможные коробочки я не нашел ничего подходящего и решил сделать корпус нужного мне размера из фанеры.
Определился с размерами будущего корпуса 10х15 см и высотой 4 см.
В качестве материала для изготовления корпуса я выбрал фанеру толщиной 6 мм.
Для проклейки стыков использовал густой клей ПВА.
Так же, для крепления передней панели приклеиваем с внутренней стороны по углам деревянные кубики, размером 2х2 см.
После просушки в течении 2-х дней шлифуем края корпуса наждачной бумагой и делаем сбоку отверстия для разъемов Ардуино USB и питания.
Отверстия высверливаются сверлом на 3 мм, дырка к дырке, затем движением сверла с бок перерезаем перегородки между дырок и зачищаем надфилем .
Ну и финальный штрих на данной стадии - покраска.
Красим наш будущий корпус акриловым лаком с баллончика.
Так как фанера хорошо впитывает краску , красим ее на 2 раза.


Вложения
10.jpg
Самодельный осциллограф на Arduino
9.jpg
Ардуино осциллограф
8.jpg
Корпус для осциллографа на Ардуино

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 11:28

Корпус готов и нам понадобится еще изготовить переднюю панель.
Сделать переднюю панель можно из куска оргстекла.
Выпиливаем кусок оргстекла размером 10х15 см.
Затем примеряем его к нашему корпусу, заранее размещаем в корпусе Ардуино с Дисплеем TFT LCD шилд, чтоб определить место размещения окна для дисплея на передней панели.
Аккуратно делаем на панели из оргстекла отметки точками по углам дисплея, оставляем запас припуск по 1 см от краев дисплея.
Затем соединяем точки , расчерчиваем на пластине из оргстекла иголкой прямоугольник и заклеиваем его полосками из изоленты.
Красим пластину из оргстекла черным акриловым лаком и ждем когда она высохнет.


Вложения
13.jpg
самодельный осциллограф
12.jpg
Осциллограф на Ардуино УНО
11.jpg
Arduino oscilloscope

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 11:43

После того как краска на передней панели высохнет, отрываем наклеенную изоленту и сверлим отверстия для кнопок, светодиодов и разъемов.
Затем вкручиваем кнопки, разъемы и вклеиваем светодиоды.

Чтобы закрыть поля вокруг дисплея , делаем в любом графическом редакторе рамку нужного размера, чертим прямоугольник с точным размером дисплея, а вокруг него пишем текст- название нашего осциллографи на Ардуино и ссылки на наш форум :D .

Ну и наконец то завершающий этап - сборка.

Перед сборкой зачищаем все края мелкой шкурочкой, что бы все было гладко и аккуратно.
Корпус я решил дополнительно обклеить пленкой из карбона.

Крепим Ардуино и TFT LCD шилд малинькими шурупами, распаиваем кнопки , разъемы, светодиоды и прикручиваем переднюю панель.


Вложения
3.jpg
Arduinoscope
1.JPG
Самодельный осциллограф
14.jpg
Осциллограф на Ардуино

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 10 май 2015, 11:47

В итоге , мы получаем самодельный осциллограф с цветным дисплеем , стоимость которого у нас вышла не более 3 000 руб, что в 10 раз меньше чем в магазинах.
Наш самодельный осциллограф может отображать сигналы с частотой до 1 МГЦ и напряжением до 50 В.
Этого вполне достаточно для изготовления и настройки различных цифровых и аналоговых устройств.

А главный ПЛЮС - мы сделали это своими руками, и это КРУТО 8-)

В следующей статье мы будем делать самодельный генератор сигналов и частотомер до 8 МГЦ с сенсорным управлением.

Все необходимые детали можно найти на Aлиэкспреcc


Вложения
16.JPG
Arduino oscilloscope
15.JPG
Осциллограф на Ардуино

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 12 май 2015, 23:36

А вот и частотомер на Ардуино готов viewtopic.php?f=98&t=1042



 
Сообщений: 7
Зарегистрирован: 26 май 2015, 21:32

Re: Осциллограф на Ардуино

Сообщение ksv2109 » 26 май 2015, 21:39

Заинтересовал Ваш проект, даже уже заказал необходимые модули.
Хотя еще ни разу не имел дела с Arduino.
Интересует принципиальная схема устройства,
не совсем понятно куда подключать входной сигнал и назначение кнопок и тумблеров на корпусе.
Заранее благодарен.



Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 28 май 2015, 08:17

ksv2109 писал(а):Заинтересовал Ваш проект, даже уже заказал необходимые модули.
Хотя еще ни разу не имел дела с Arduino.
Интересует принципиальная схема устройства,
не совсем понятно куда подключать входной сигнал и назначение кнопок и тумблеров на корпусе.
Заранее благодарен.


Вход осциллографа подключается к аналоговому входу А5 через резистор 100 ом.
Кнопки:
1 - Кнопка включения питания
2 - Кнопка переключения входного делителя напряжения 1:10.
3 - Кнопка сброса контроллера ардуино
4 - Кнопка смены временных режимов (пока не реализовано в скетче)

Разъемы:
1- Выход эталонного генератора на 1 МГц с кварцевой стабилизацией частоты.
2- Вход осциллографа.
Боковые разъемы питание и USB от Ардуино.


Схему выложу позже



 
Сообщений: 7
Зарегистрирован: 26 май 2015, 21:32

Re: Осциллограф на Ардуино

Сообщение ksv2109 » 28 май 2015, 21:44

Доброе время суток
Спасибо за ответ, получил сегодня модули, теперь бегаю с бубном :D , дисплей оказался с контроллером spfd5408.
Полдня потратил на поиски библиотеки, теперь пытаюсь разобраться как эту библиотеку срастить с скетчом, пока не получается. Еще совсем слабый в этом вопросе...
На всякий случай прилагаю библиотеку, может что подскажете


Вложения
TFTLCD-Library-master.zip
TFTLCD
(85.89 KiB) Скачиваний: 3613

Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 28 май 2015, 21:52

Здравствуйте!

Для начала советую Вам загрузить в Ардуину тестовый скетч который идет в комплекте с библиотекой, там должна быть папка с названием example,
в ней могут быть примеры , работа с графикой , отображение текста, картинок, работа с сенсором. Попробуйте каждый из примеров, если они будут нормально работать без ошибок, то можно будет двигаться дальше.
А библиотечку Вашу что то не нашел во вложении (((



 
Сообщений: 7
Зарегистрирован: 26 май 2015, 21:32

Re: Осциллограф на Ардуино

Сообщение ksv2109 » 28 май 2015, 22:00

Вложенное подкорректировал, тестовый скетч пробовал, пошел тест только с приложенной библиотекой .



Аватар пользователя
 
Сообщений: 799
Зарегистрирован: 27 мар 2013, 22:12

Re: Осциллограф на Ардуино

Сообщение -=dp=- » 07 июн 2015, 22:25

Всем здравствуйте!
По просьбе общественности накидал на досуге схему осциллографа, выкладываю на форум.


Вложения
схема_осциллографа.JPG
Схема осциллографа на Ардуино УНО

 
Сообщений: 7
Зарегистрирован: 26 май 2015, 21:32

Re: Осциллограф на Ардуино

Сообщение ksv2109 » 08 июн 2015, 18:39

Доброе время суток
Подружить библиотеку со скетчом пока не удалось :(
Но по схеме внес бы не большое изменение: по аналоговому входу поставил бы стабилитроны от случайной подачи напряжения больше 5 в.
И еще вопрос: по скетчу видно , что запланирован второй луч, каким образом будет выполнятся смещение лучей относительно друг друга?



След.

Вернуться в Устройства на Ардуино

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3