Se afișează postările cu eticheta AD9850. Afișați toate postările
Se afișează postările cu eticheta AD9850. Afișați toate postările

joi, 16 iulie 2015

EM125 - osciloscop si multimetru portabil

   De curand am intrat in posesia unui aparat de masura mai deosebit, care are functii de osciloscop cu masurare tensiune (varf al varf, medie, efectiva) si frecventa semnal, respectiv aparat de masura pentru rezistente, diode, continuitate, tensiune continua si alternativa si condensatoare.
   Aparatul produs de ALL-SUN (E-SUN) are cod EM125  si are un pret mediu de 100$ (90..130$):
   Produsul se livreaza cu o gentuta de transport cu 2 compartimente, in cel mare se pune multimetrul si sondele de masura clasice
si in cealalt compartiment se pune sonda osciloscopului, eventual incarcatorul (care se livreaza cu priza americana, dar s egasesc adaptoare).
   Partea de osciloscop m-a incantat cel mai mult, de fapt pentru asta l-am vrut.
   Caracterisitici generale:
- rezolutie ecran: 128x64 pixeli, cu led de fundal
- alimentare: acumulator Li-Ion 3,7V / 1Ah
- incarcator acumulator: tensiune alimentare 100..240Vca, tensiune iesire 5Vcc +10%, 1A
- dimensiuni de gabarit: 174x92x40mm
- greutate: 330g.
   Caracterisiticile tehnice ale osciloscopului sunt:
- banda de frecventa: 25MHz la -3dB
- rata de esantionare: max. 100MSa/s
- canale: 1
- cuplare masurare: AC, DC (tensiune alternativa, fara componenta continua)
- timp de raspuns: max.17,5ns
- impedanta de intrare 1Mohm, <20pF
- tensiune de intrare maxima: 300V
- rezolutie pe verticala: 8 biti
- sensibilitate pe verticala: 50mV..20V/diviziune, in 9 trepte
- rezolutie pe orizontala: 10ns/diviziune
- baza de timp, pe orizontala: 10ns..5s/diviziune, in 27 trepte
- dimensiune imagine: 0,1k/canal
- mod de declansare baza de timp: automat, pe front pozitiv semnal, pe front negativ semnal
   Caracterisiticile tehnice generale ale multimetrului:
- afisare: cifra max. 6000 
- tensiune maxima la intrare: 600V
- test continuitate: pe domeniu de 600 ohmi, avertizare acustica la rezistenta mai mica de 25 ohmi
- test diode: daca tensiunea de pe dioda este mai mare de 2V sau testerele sunt in gol, pe afisaj apare "OL", iar daca tensiunea de dioda este mai mica de 0,25V, apre si avertizare acustica
- masurare condensatori: 6nF..6mF, in 7 trepte
- masurare rezistenta: 600 ohmi.. 60Mohmi, in 6 trepte
- masurare tensiune: 6V..600V, in 3 trepte
   Precizia pe partea de osciloscop este de +3%, sonda fara divizare (notata x1) are timp de reactie de 23,3ns, banda de frecventa 15MHz, impedanda de 1Mohm, capacitatea de 46pF, respectiv pe divizare cu 10 (notata cu x10) are timp de reactie de 17,5ns, banda de frecventa 25MHz, impedanda de 10Mohm, capacitatea de 15pF.
   Precizia ca multimetru (in conditii ideale), pe domeniul de tensiune continua e de +0,5%, pe domensiul de tensiune alternativa al frecvente scazute, sub 400Hz, este de +1%, pana la 2kHz este de +5%.
   La masurare rezistenta mai mici de 6Mohmi precizia este de +1%, iar peste de +2%, la masurare condesatoare mai mici de 6nF, precizia este de +5%, pana la 60uF este de +3%, apoi pana la 600uF de 5%, iar peste de +8%.
   Pe domeniul de testare al diodelor se foloseste tensiune de 2V la un curent de 2mA, avand avertizare sonora la cadere de tensiune de 0,25V, iar a continuitate la rezistent amai mica de 25 ohmi.
   Dupa atatea date, trecem si la partea practica... ca multimetru, are autoscalare.
   Am facut masuratori pentru:
- rezistenta:
- condensator nepolarizat:
- condensator electrolitic:
si modul de afisare pe tensiune continua:
respectiv tensiune alternativa
   Cand l-am primit, primul test ca osciloscop, l-am facut folosindu-ma de o placa Arduino Mega la care am folosit-o ca generator cu factor de umplere variabil (PWM):
   Am facut un prim filmulet, numit EM125 - osciloscop digital + multimetru
 
   Ulterior, am pus osciloscopul pe un transformator de la un televizor Sport 251, care intra in componenta unui alimentator cu LM317:
- pe secundar, cu sonda fara divizare:
- in primar, cu sonda pe divizare cu 10:
iar filmuletul aferent se numeste EM125 - osciloscop digital si multimetru (3)
   Avand un sistem de alimentare la distanta, care se compune dintr-un oscilator si un receptor, am pus sonda pe bobina emitatorului obtinand:
 
  Frecventa masurata de aparat este de 63kHz, iar vanzatorul sistemului de alimentare la distanta indica 125kHz, asa ca am zis sa testez si partea de masurare a frecventei; pentru asta am folosit generatorul de semnal realizat cu AD9850 controlat de un Arduino prin intermediul unui ecran tactil si rezultatele sunt multumitoare:
- semnal sinusoidal cu frecventa de 100Hz:
- semnal sinusoidal cu frecventa de 10kHz:
- semnal sinusoidal cu frecventa de 100kHz
- semnal sinusoidal de 1MHz
- semnal sinusoidal cu frecventa de 10MHz:
- semnal dreptunghiular cu frecventa de 1kHz:
- semnal dreptunghiular cu frecventa de 10kHz:
- semnal dreptunghiular cu frecventa de 100kHz:
- semnal dreptunghiular cu frecventa de 1MHz:
   Am facut si 2 filmulete, in primul am constatat ca pe autocautare gaseste greu baza de timp corecta la semnal sinusoidal cu frecvente mici, sub 10-20kHz, realizand ulterior ca daca am cablul sondei desfacut (nu bucla, cum a fost impachetat) nu mai capteaza frecvente parazite, asa ca autocautarea e ok:

   Concluzia, pana acum, e ca e util, portabil si destul de precis !
   Ca puncte minus: incarcatorul cu priza americana, dar se rezova cu adaptor, iar butoanele sunt cam firave, mai ales cel de pornire, care e cu retinere...

marți, 31 martie 2015

Generator de semnal cu AD9850, afisaj tactil si Arduino

   Fata de generatorul de semnal cu AD9850 cu schimbare a frecventei cu ajutorul unui encoder si prezentarea informatiei pe un afisaj alfanumeric de 16x2 caractere, care a fost ptrezentat in articolul Generator de semnal cu AD9850 si Arduino, de data aceasta va prezint un proiect original, in care ma folosesc de un afisaj grafic color care este si tactil, in stilul ecranelor de tableta.
   Acest ecran l-am prezentat in articolul Ecran tactil de 2,4" (6cm) si necesita libraria SWTFT.
   Ecranul este montat pe un shield (placa adaptoare) pentru Arduino Uno sau Mega si are conectati aproape toti pinii placii Arduino Uno:
   Deoarece nu folosesc cardul microSD, m-am gandit sa fac un alt shield intermediar, care sa imi conecteze modulul de generator de semnal cu AD9850. 
   Schema mea este:
iar cablajul:
   Fizic, montajul asamblat, respectiv componentele atata asa:
   Dupa mai multe teste pana am obtinut o tastatura virtuala, am reusit sa fac un sketch care permite introducerea frecventei dorite prin folosirea functiei de ecran tactil, dupa cum se vede in filmuletul generator de semnal cu AD9850 si comenzi de pe ecran tactil (2)
   Pentru a verifica frecventa generata, am folosit alta placa Arduino cu sketch de frecventmetru, cum este prezentat in articolul de la http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/.
   Sketch-ul facut de mine nu este unul optimizat, ci unul functional, in care am folosit, pentru comanda lui AD9850 informatiile de la http://webshed.org/wiki/AD9850_Arduino:
// Code for TFT shield display provided by Smoke And Wires
// http://www.smokeandwires.co.nz
// This code has been taken from the Adafruit TFT Library and modified
//  by us for use with our TFT Shields / Modules
// For original code / licensing please refer to
// https://github.com/adafruit/TFTLCD-Library

// adapted sketch by niq_ro from http://arduinotehniq.blogspot.com/
// http://nicuflorica.blogspot.ro/
// http://www.tehnic.go.ro
// http://www.niqro.3x.ro
// original virtual keyboard with DDS with AD8959 by niq_ro
// ver. 1m4a: 30.03.2015, Craiova - Romania

#include <Adafruit_GFX.h>    // Core graphics library
#include "SWTFT.h" // Hardware-specific library

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
// #define LCD_CS A3 // Chip Select goes to Analog 3
// #define LCD_CD A2 // Command/Data goes to Analog 2
// #define LCD_WR A1 // LCD Write goes to Analog 1
// #define LCD_RD A0 // LCD Read goes to Analog 0

// #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).

#include <TouchScreen.h>
#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);


// Assign human-readable names to some common 16-bit color values:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define ROZ     0xFBE0
#define GRI     0xBDF7
// http://stackoverflow.com/questions/13720937/c-defined-16bit-high-color
// http://wiibrew.org/wiki/U16_colors

SWTFT tft;

#define BOXSIZE 80
#define BOXSIZE2 60
#define PENRADIUS 3

int ics; 
int numar, ics0, igr0, pas; 

#include <EEPROM.h>
long n1, n2, n3, n4, n5, n6, n7, n8; // number for frequency;
long frecv; // value for frecvency;
byte cifru; 

//Setup some items
//#define W_CLK 13   // Pin 13 - connect to AD9850 module word load clock pin (CLK)
#define CLOCK 13
//#define FQ_UD 12   // Pin 12 - connect to freq update pin (FQ)
#define LOAD 12
#define DATA 11   // Pin 11 - connect to serial data load pin (DATA)
#define RESET 10  // Pin 10 - connect to reset pin (RST) 
//#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
#define DDS_CLOCK 125000000 // http://webshed.org/wiki/AD9850_Arduino
//#define DDS_CLOCK 125000000

void setup(void) {

pinMode (DATA,  OUTPUT); 
pinMode (CLOCK, OUTPUT); 
pinMode (LOAD,  OUTPUT); 
pinMode (RESET, OUTPUT); 
  
AD9850_init();
AD9850_reset();
//SetFrequency(15000);
zaibar();
SetFrequency(frecv);
  
  Serial.begin(9600);
  Serial.print(F("DDS with AD9850 "));
  Serial.println("made by niq_ro");
  
  tft.reset();
  
  uint16_t identifier = tft.readID();

  Serial.print(F("LCD driver chip: "));
  Serial.println(identifier, HEX);
 
  tft.begin(identifier);

  tft.fillScreen(BLACK);
  tft.fillRect(0, 0, 320, 240, BLACK);
//  tft.setRotation(0);
//  tft.setCursor(5, 100);
  tft.setTextColor(RED);  tft.setTextSize(2);
//  tft.println("Acces control");
  tft.setCursor(30, 120);
  tft.println("DDS with AD9850");
  tft.setCursor(20, 150);
  tft.setTextColor(YELLOW);
  tft.println("on touch display");
  tft.setCursor(70, 180);
  tft.setTextColor(BLUE);
  tft.println("by niq_ro");
  tft.setCursor(75, 210);
  tft.setTextColor(ROZ);
  tft.println("ver. 1.4a");
  

delay(2000);
tft.fillRect(0, 0, 320, 240, BLACK);

numar = 0;
ics0 = 10;
igr0 = 280;
pas = 18;
frecv = 0;
  
//tft.setRotation(0);
 stergere ();

 cifre ();
 caractere();

}

#define MINPRESSURE 10
#define MAXPRESSURE 1000


void loop()
{
    
  // Recently Point was renamed TSPoint in the TouchScreen library
  // If you are using an older version of the library, use the
  // commented definition instead.
  // Point p = ts.getPoint();
  TSPoint p = ts.getPoint();

  // if sharing pins, you'll need to fix the directions of the touchscreen pins
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
  //   tft.setTextSize(4);
     // scale from 0->1023 to tft.width
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
 
    if (p.y < BOXSIZE2) {   // fist line (0, 1 & 2)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, GRI); // one       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 20);
         tft.println("1");
 //        caracter(1);
int ics1 = ics0+pas*numar;
caracters(1,ics1,igr0);
cifru = 1;
         delay (200);
         tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, RED); // one       
         tft.setTextColor(WHITE);
         tft.setCursor(30, 20);
         tft.println("1");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, GRI);  // two
         tft.setTextColor(BLACK);
         tft.setCursor(110, 20);
         tft.println("2");
//         caracter(2);
int ics1 = ics0+pas*numar;
caracters(2,ics1,igr0);
cifru = 2;
         delay (200);
         tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, YELLOW);  // two
         tft.setTextColor(BLACK);
         tft.setCursor(110, 20);
         tft.println("2");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, GRI); // three
         tft.setTextColor(BLACK);
         tft.setCursor(190, 20);
         tft.println("3");
//         caracter(3);
int ics1 = ics0+pas*numar;
caracters(3,ics1,igr0);
cifru = 3;
         delay (200);
         tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, BLUE); // three
         tft.setTextColor(WHITE);
         tft.setCursor(190, 20);
         tft.println("3");
       }
   //      numar = numar + 1;
    }
    
  if ((p.y < BOXSIZE2*2) && (p.y > BOXSIZE2)) {   // second line (4, 5 & 6)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 80);
         tft.println("4");
int ics1 = ics0+pas*numar;
caracters(4,ics1,igr0);
cifru = 4;
//         caracter(4);
         delay (200);
         tft.fillRect(0, BOXSIZE2, BOXSIZE, BOXSIZE2, CYAN); // four 
         tft.setTextColor(BLACK);
         tft.setCursor(30, 80);
         tft.println("4");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 80);
         tft.println("5");
int ics1 = ics0+pas*numar;
caracters(5,ics1,igr0);
cifru = 5;
//         caracter(5);
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GREEN);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 80);
         tft.println("5");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 80);
         tft.println("6");
int ics1 = ics0+pas*numar;
caracters(6,ics1,igr0);
cifru = 6;
//         caracter(6);
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, MAGENTA); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 80);
         tft.println("6");
       }
    //     numar = numar + 1;
  }

if ((p.y < BOXSIZE2*3) && (p.y > BOXSIZE2*2)) {   // second line (7, 8 & 9)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 140);
         tft.println("7");
int ics1 = ics0+pas*numar;
caracters(7,ics1,igr0);
cifru = 7;
//         caracter(7);
         delay (200);
         tft.fillRect(0, BOXSIZE2*2, BOXSIZE, BOXSIZE2, RED); // four 
         tft.setTextColor(WHITE);
         tft.setCursor(30, 140);
         tft.println("7");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 140);
         tft.println("8");
int ics1 = ics0+pas*numar;
caracters(8,ics1,igr0);
cifru = 8;
//         caracter(8);
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, YELLOW);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 140);
         tft.println("8");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 140);
         tft.println("9");
//         caracter(9);
int ics1 = ics0+pas*numar;
caracters(9,ics1,igr0);
cifru = 9;
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, BLUE); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 140);
         tft.println("9");
       }
  //       numar = numar + 1;
 }

if ((p.y < BOXSIZE2*4) && (p.y > BOXSIZE2*3)) {   // second line (*, 0 & #)
/*
       if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 200);
         tft.println("*");
int ics1 = ics0+pas*numar;
caracters(10,ics1,igr0);
//         caracter(10);
         delay (200);
         tft.fillRect(0, BOXSIZE2*3, BOXSIZE, BOXSIZE2, CYAN); // four 
         tft.setTextColor(BLACK);
         tft.setCursor(30, 200);
         tft.println("*");

       } else
   */   
       if ((p.x > BOXSIZE) && (p.x < BOXSIZE*2))  {
         tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 200);
         tft.println("0");
//         caracter(0);
int ics1 = ics0+pas*numar;
caracters(0,ics1,igr0);
cifru = 0;
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GREEN);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 200);
         tft.println("0");
         
        }
 /*
        else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 200);
         tft.println("#");
int ics1 = ics0+pas*numar;
caracters(11,ics1,igr0);
//         caracter(11);
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, MAGENTA); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 200);
         tft.println("#");
       }
*/       
       
// numar = numar + 1;
     }
//caractere();

  numar = numar + 1;
memorie(cifru,numar);
Serial.print(cifru);

  if (numar == 2) numar = numar +1;
  if (numar == 6) numar = numar +1;

  if (numar == 10) {
    tft.setTextColor(YELLOW);
     tft.setTextSize(3);
         tft.setCursor(200, 250);
         tft.println("ok");

 Serial.print(" --> "); 
// read eeprom memory and calculate the stored number (freqvency)
zaibar(); 

 Serial.print(frecv);
 Serial.println("Hz");
 Serial.println("---------");
  Serial.print(frecv);
/*
  Serial.println(frecv);
          Serial.println("---------");
          for (int j=11; j<19; j++)
          {
           Serial.print(EEPROM.read(j));
          }
 */
   delay (3000);
 tft.fillRect(0, 310 , 239, 5, BLACK);   // for testing   
 tft.fillRect(199, 249 , pas*2+2, 30, BLACK);   // for testing   
//   caractere();
   numar = 0;
        
  }
  }

  
}  // end main loop


void cifre ()
{
// number for "buttons"
 tft.setTextSize(4);
 tft.setTextColor(WHITE);
 tft.setCursor(30, 20);
 tft.println("1");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 20);
 tft.println("2");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 20);
 tft.println("3");
 tft.setTextColor(BLACK);
 tft.setCursor(30, 80);
 tft.println("4");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 80);
 tft.println("5");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 80);
 tft.println("6");
 tft.setTextColor(WHITE);
 tft.setCursor(30, 140);
 tft.println("7");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 140);
 tft.println("8");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 140);
 tft.println("9");
// tft.setTextColor(BLACK);
// tft.setCursor(30, 200);
// tft.println("*");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 200);
 tft.println("0");
// tft.setTextColor(WHITE);
// tft.setCursor(190, 200);
// tft.println("#");
}

void stergere ()
{
//      Serial.println("erase");
// firs line
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, RED); // one
  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, YELLOW);  // two
  tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, BLUE); // three
// second line
  tft.fillRect(0, BOXSIZE2 , BOXSIZE, BOXSIZE2, CYAN);  // four
  tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GREEN);  // five
  tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, MAGENTA);  // six
// 3rd line
  tft.fillRect(0, BOXSIZE2*2 , BOXSIZE, BOXSIZE2, RED);  // seven
  tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, YELLOW);  // eight
  tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, BLUE);  // nein
// 4th line
//  tft.fillRect(0, BOXSIZE2*3 , BOXSIZE, BOXSIZE2, CYAN);  // *
  tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GREEN);  // zero
//  tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, MAGENTA);  // #

  cifre ();  
    }

void caracter (int numar)
{
 tft.setTextSize(4);
 tft.setTextColor(WHITE);
 tft.setCursor(110, 280);
 tft.fillRect(0, 260 , 240, 59, BLACK);  // *
if (numar == 0) tft.println("0");
if (numar == 1) tft.println("1");
if (numar == 2) tft.println("2");
if (numar == 3) tft.println("3");
if (numar == 4) tft.println("4");
if (numar == 5) tft.println("5");
if (numar == 6) tft.println("6");
if (numar == 7) tft.println("7");
if (numar == 8) tft.println("8");
if (numar == 9) tft.println("9");
//if (numar == 10) tft.println("*");
//if (numar == 11) tft.println("#");
}

void caractere()
{
 tft.setTextSize(2);
tft.fillRect(0, 241 , 240, 79, BLACK);  // *
 tft.setTextColor(WHITE);
 tft.setCursor(10, 258);
 tft.println("DDS with AD9850");
 tft.setTextSize(3);
 tft.setCursor(10, 280);
// tft.println("??.???.???Hz");
citiremem();
// tft.println(EEPROM.read(11)); 
}

void caracters (int numar, int ics, int igr)
{
 tft.setTextSize(3);
 tft.setTextColor(WHITE);
//tft.drawLine(x1, y1, x2, y2, color); // line model
 tft.drawLine(ics, igr+32, ics+pas, igr+32, BLUE);


 tft.setCursor(ics, igr);
 tft.fillRect(ics, igr-2 , pas, 30, YELLOW);   // for testing
 delay(100);
 tft.fillRect(ics, igr-2 , pas, 30, BLACK);  

if (numar == 0) tft.println("0");
if (numar == 1) tft.println("1");
if (numar == 2) tft.println("2");
if (numar == 3) tft.println("3");
if (numar == 4) tft.println("4");
if (numar == 5) tft.println("5");
if (numar == 6) tft.println("6");
if (numar == 7) tft.println("7");
if (numar == 8) tft.println("8");
if (numar == 9) tft.println("9");
//if (numar == 10) tft.println("*");
//if (numar == 11) tft.println("#");
tft.setTextSize(4);
}


void memorie (byte cifra, int pozitie)
{
  if (pozitie == 1) {
    EEPROM.write(11,cifra); // cifra zeci de MHz
  //  Serial.print(EEPROM.read(11));
  }
  if (pozitie == 2) {
    EEPROM.write(12,cifra); // cifra MHZ
 //   Serial.print(EEPROM.read(12));
  }  
  if (pozitie == 4) {
    EEPROM.write(13,cifra); // cifra sute de kHz
//   Serial.print(EEPROM.read(13));
  }
  if (pozitie == 5) {
    EEPROM.write(14,cifra); // cifra zeci de kHz
 //   Serial.print(EEPROM.read(14));
  }
  if (pozitie == 6) {
    EEPROM.write(15,cifra); // cifra kHz
 //   Serial.print(EEPROM.read(15));
  }   
  if (pozitie == 8) {
    EEPROM.write(16,cifra); // cifra sute de Hz
  //  Serial.print(EEPROM.read(16));
  }
  if (pozitie == 9) {
    EEPROM.write(17,cifra); // cifra zeci de Hz
 //   Serial.print(EEPROM.read(17));
  }
  if (pozitie == 10) {
    EEPROM.write(18,cifra); // cifra Hz
 //   Serial.print(EEPROM.read(18));
  }
}

void citiremem ()
{
//tft.setTextSize(3);
// tft.setCursor(10, 280);
 for (int ji=11; ji<19; ji++)
{
  int nr = EEPROM.read(ji);

if (nr == 0) tft.print("0");
if (nr == 1) tft.print("1");
if (nr == 2) tft.print("2");
if (nr == 3) tft.print("3");
if (nr == 4) tft.print("4");
if (nr == 5) tft.print("5");
if (nr == 6) tft.print("6");
if (nr == 7) tft.print("7");
if (nr == 8) tft.print("8");
if (nr == 9) tft.print("9");

if (ji==12) tft.print(".");
if (ji==15) tft.print(".");
}
tft.println("Hz");
}


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

  digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}


void zaibar()
{
 n1 = EEPROM.read(11); //Serial.print(n1);
 n2 = EEPROM.read(12); //Serial.print(n2);
 n3 = EEPROM.read(13); //Serial.print(n3);
 n4 = EEPROM.read(14); //Serial.print(n4);
 n5 = EEPROM.read(15); //Serial.print(n5);
 n6 = EEPROM.read(16); //Serial.print(n6);
 n7 = EEPROM.read(17); //Serial.print(n7);
 n8 = EEPROM.read(18); //Serial.print(n8);
 frecv = n1*10000000 + n2*1000000+n3*100000+n4*10000+n5*1000+n6*100+n7*10+n8;
}  
   
29.7.2015
   Am facut si filmuletul generator de semnal cu AD9850 si osciloscop EM125 (2) in care se vad si formele de unda pe un osciloscop portabil:

sâmbătă, 28 martie 2015

Generator de semnal cu AD9850 si Arduino

   Un generator de semnal este util pentru a testa diverse montaje, fie audio, fie de radiofrecventa, asa ca m-am hotarat, cu greu, ce-i adevarat, sa imi fac si eu un asemenea generator de semnal cu afisarea frecventei pe un ecran alfanumeric lcd cu 16 coloane si 2 randuri, iar frecventa se schimba cu ajutorului unui encoder.
   Proiectul, care este baza experimentului, se gaseste la adresa http://www.ad7c.com/projects/ad9850-dds-vfo/ si foloseste memorarea frecventei in EEPROM (la repornire vom avea frecventa memorata):
   Schema de baza este cea din articol, la care am scos butonul de frecventa intermediara.. a mea ramanand asa:
   Dupa incarcarea sketch-ului de pe site-ul mentionat mai sus, am obtinut pe una din iesirile de semnal dreptunghiular:
 
 
 
 
 
 
 
iar pe una de semnal sinusoidal (dupa ce am umblat la semireglabilul de pe modul, ca nu aparea sinusoida... deci e pun la casa omului un osciloscop):
 
 
 
 
   Pentru a verifica frecventa generata, am folosit o alta placa Arduino cu sketch de frecventmetru (cum este prezentat in articolul de la http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/ si l-am prezentat si eu in articolul Frecventmetru cu.. Arduino:
)
 
 
   Sketch-ul folosit de mine, cu foarte mici modificari fata de cel original este:
/*
Main code by Richard Visokey AD7C - http://www.ad7c.com
Revision 2.0 - November 6th, 2013
adapted sketch 1.2 - january 1st, 2015 - by Nicu Florica - http://www.tehnic.go.ro
http://nicuflorica.blogspot.ro/
http://arduinotehniq.blogsopt.com/
*/

// Include the library code
#include <LiquidCrystal.h>
#include <rotary.h>
#include <EEPROM.h>

//Setup some items
#define W_CLK 8   // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 9   // Pin 9 - connect to freq update pin (FQ)
#define DATA 10   // Pin 10 - connect to serial data load pin (DATA)
#define RESET 11  // Pin 11 - connect to reset pin (RST) 
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses.  Must be interrupt pins.
LiquidCrystal lcd(13, 12, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
int_fast32_t rx=7200000; // Starting frequency of VFO
int_fast32_t rx2=1; // variable to hold the updated frequency
int_fast32_t increment = 1; // starting VFO update increment in HZ.
int buttonstate = 0;
String hertz = "1 Hz";
int  hertzPosition = 6;
byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ;  //Placeholders
String freq; // string to hold the frequency
int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup
int memstatus = 1;  // value to notify if memory is current or old. 0=old, 1=current.

int ForceFreq = 0;  // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory.  YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!

void setup() {
  pinMode(A0,INPUT); // Connect to a button that goes to GND on push
  digitalWrite(A0,HIGH);
  lcd.begin(16, 2);
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT); 
  pulseHigh(RESET);
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);  // this pulse enables serial mode on the AD9850 - Datasheet page 12.
  lcd.setCursor(hertzPosition,1);    
  lcd.print(hertz);
   // Load the stored frequency  
  if (ForceFreq == 0) {
    freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
    rx = freq.toInt();  
  }
}


void loop() {
  if (rx != rx2){    
        showFreq();
        sendFrequency(rx);
        rx2 = rx;
      }
      
  buttonstate = digitalRead(A0);
  if(buttonstate == LOW) {
        setincrement();        
    };

  // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
    if(memstatus == 0){   
      if(timepassed+2000 < millis()){
        storeMEM();
        }
      }   
}


ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result) {    
    if (result == DIR_CW){rx=rx+increment;}
    else {rx=rx-increment;};       
      if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT
      if (rx <=1){rx=rx2;}; // LOWER VFO LIMIT
  }
}



// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {  
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850.  You can make 'slight' tuning variations here by adjusting the clock frequency.
  for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
  pulseHigh(FQ_UD);  // Done!  Should see output
}
// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data)
{
  for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
}

void setincrement(){
  if(increment == 1){increment = 10; hertz = "10 Hz"; hertzPosition=5;}
  else if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;}
  else if (increment == 50){increment = 100;  hertz = "100 Hz"; hertzPosition=4;}
  else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;}
  else if (increment == 500){increment = 1000; hertz="1 kHz"; hertzPosition=6;}
  else if (increment == 1000){increment = 2500; hertz="2.5 kHz"; hertzPosition=4;}
  else if (increment == 2500){increment = 5000; hertz="5 kHz"; hertzPosition=6;}
  else if (increment == 5000){increment = 10000; hertz="10 kHz"; hertzPosition=5;}
  else if (increment == 10000){increment = 100000; hertz="100 kHz"; hertzPosition=4;}
  else if (increment == 100000){increment = 1000000; hertz="1 MHz"; hertzPosition=6;}  
  else{increment = 1; hertz = "1 Hz"; hertzPosition=6;};  
   lcd.setCursor(0,1);
   lcd.print("                ");
   lcd.setCursor(hertzPosition,1); 
   lcd.print(hertz); 
   delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
};

void showFreq(){
    millions = int(rx/1000000);
    hundredthousands = ((rx/100000)%10);
    tenthousands = ((rx/10000)%10);
    thousands = ((rx/1000)%10);
    hundreds = ((rx/100)%10);
    tens = ((rx/10)%10);
    ones = ((rx/1)%10);
    lcd.setCursor(0,0);
    lcd.print("                ");
   if (millions > 9)
   {
       lcd.setCursor(1,0);
      }
   else 
   {
        lcd.setCursor(2,0); 
   }
    lcd.print(millions);
    lcd.print(",");
    lcd.print(hundredthousands);
    lcd.print(tenthousands);
    lcd.print(thousands);
    lcd.print(".");
    lcd.print(hundreds);
    lcd.print(tens);
    lcd.print(ones);
    lcd.print(" MHz  ");
    timepassed = millis();
    memstatus = 0; // Trigger memory write
};

void storeMEM(){
  //Write each frequency section to a EPROM slot.  Yes, it's cheating but it works!
   EEPROM.write(0,millions);
   EEPROM.write(1,hundredthousands);
   EEPROM.write(2,tenthousands);
   EEPROM.write(3,thousands);
   EEPROM.write(4,hundreds);       
   EEPROM.write(5,tens);
   EEPROM.write(6,ones);   
   memstatus = 1;  // Let program know memory has been written
   lcd.setCursor(1,15);
   lcd.print("*");
   delay(500);
   lcd.setCursor(1,15);
   lcd.print(" ");
 
};
   Am facut is niste filmulete, care prezinta mai bine modul de functionare:
generator de semnal cu AD9850 si reglaj cu encoder rotativ
generator de semnal cu AD9850 si reglaj cu encoder rotativ (2)
generator de semnal cu AD9850 si reglaj cu encoder rotativ (3)
Arduino AD9850 DDS + Arduino frequencymeter
   Avand un afisaj cu touch, vreau sa fac un generator cu AD9850 la care sa introduc frecventa prin atingere, dupa cum e prezentat in filmuletul preliminar numit adaptor pentru afisaj TFT cu senzor tactil si generator semnal cu AD9850 (2)