MCP4725 DAC kezelése Arduinóval

 

2020-10-24

A MCP4725 DAC chipet a Microchip gyártja, 12 bites, I2C soros buszon keresztül vezérelhető. Több se kellett nekem, lassan két hónapja, hogy Csang bácsiéktól rendeltem 5 db DAC panelt, 4 USD-ért.

A DAC annyit tesz, hogy Digital to Analog Convereter, vagyis egy számot vár a bemenete, a kimenetén pedig annak megfelelő feszültség fog megjelenni. Ez a DAC szimpla 2,7V..5V tápeszültség igényel. I2C soros buszon keresztül programozható, ami azért jó, mert a föld lábon kívűl csak két vezetéket igényel, egy adatot és egy órajelet. Most az egész I2C buszt nem fogom elmesélni, aki nem ismeri és érdekli, olvasson utána. A I2C buszon 7 biten címezhetők a különböző chipek, ebből a felső 4 gyárilag fix szokott lenni (chip függő), az alsó 3-at meg kivezetik, hogy az egyszerű mérnök ember több azonos chipet is tudjon használni, vagy ha valamely chipeknek azonos gyári címe lenne, el tudja őket különíteni. A Microchip mérnökeinek áldozatos munkával sikerült két SMD lábat megspórolniuk, és így nyereségessé tenniük cégüket (:. Csak az A0 láb lett kivezetve, alapból le van földelve, így a modul címe 0x60. Az ADDR keretbe tudjuk a cím lábat VCC-re átforrasztani, és akkor a címe 0x61 lesz.

Azon gondolkodtam, hogy lehet... egyszer... majd... több DAC-ot is akarok használni. Az A0 lábat kivezettem, így az Arduino egyik lábáról tudom kapcsolni. Mindegyik DAC A0 lábát HIGH-ba kapcsolom, vagyis mindegyik a 0x61-en fog figyelni. A kiválasztot DAC A0 lábát fogom LOW-ba állítani, ami ekkor a 0x60 címen fogja várni az adatot. Így teljesen konvencionális LOW aktív Chip Select-ként fogom tudni használni, a kiválasztott DAC-ot a 0x60 címen fogom tudni írni. Nemcsak a kép néz ki bénán, hanem annak az ellenállás lábnak a felforrasztásával is megkínlódtam. Jobban jár az ember, ha direktbe az SMD tok lábára forrasztja a kivezetést.

Még egy kép a teljes panelról. A DAC-nak nincs külön referencia feszültség bemenete, a tápfesztség szolgál referenciának. Ez annyiból gond, ha USB-ről tápláljuk a kapcsolásunkat, mint most én, nagyjából olyan 4,4..4,6V közötti tápfeszt mérhetünk. Szóval ha hasznáni is akarjuk a DAC-ot, akkor gondoskodni kell egy stabil és pontos tápról.

Nézegessük meg alaposabban MCP4725 DAC-ot, hogy értsük is majd a vezérlő programot. Első közelítésben nem értettem, miért kell egy DAC-ba EEPROM?

Ez úgy van, hogy a beállításainkat be tudjuk írni egy "árnyék" EEPROM regiszterbe, és bekapcsolás után, ezzel fog indulni. A gyári alapbeállítás nem az, mint szerintem minden normális áramkörnél, hogy nagy impedanciás állapotba áll minden kimenet, hanem ennek a DAC-nak a kimenete fél tápfeszre áll. Megkönnyíti a munkát, de nagyon amatőr.

Lehet vele mindenfélét csinálni, de én nem akarom az EEPROM-ot írni, a DAC regisztereit meg minek olvasnám, ha én programoztam fel? Ezért azután a legegyszerűbb vezérlést programoztam csak le, akinek mégis szüksége lenne a többi dologra, forgassa bátran a chip PDF-jét, meg le is lehet tölteni az Arduino web lapjáról a "szabványos" library-t. Az én fejem nagyon nem szabványos, azt a sok marhaságot, amit abba beleírtak... Nézzük, az első byte a chip címe, az A2, meg az A1 az átverés, mert ugye nem lettek kivezetve, fixen 0, 0. A második byte 2 felső bitje határozza, meg hogy milyen parancsot küldünk, de mi csak "Fast Mode Write Command"-ot fogunk küldeni, tehát 0, 0 lesz az értékük. Következnek a PD1, PD0 bitek, ha ezek 0, 0, akkor működik a DAC. Ha 1, 1, akkor a kimenet nagy impedanciás állapotba kerül, és a chip áramkörei lekapcsolódnak. Ez energia takarékoskodáshoz lehet jó. Lehet mást is beállítani, szerintem érdektelen. Ez után jön végre a 12 adat bit, amivel be tudjuk állítani a kimenetet.

Lássuk végre a medvét, akarom mondani a programot. Nem szedtem szét külön library-ra meg programra. Szerintem elég egyszerű lett. A D7 lábat használtam Chip Select-nek. Ha nem akarunk Chip Select-et használni, állítsunk be 0-t. A SETUP-ban találtok mintát, hogyan lehet használni az objektumot és ellenőrizni a chip-et. Ha valaki szkópon szeretné nézegetni az DAC kimentét, a LOOP-ban vagy egy egyszerű fűrészjel generátor.


/******************************************************************************
*   Author       -  Kiraly Tibor
*                   http://www.tkiraaly.hu
*   Date         -  2020.10.24.
*   Chip         -  MCP4725, Arduino Nano
*   Compiler     -  Arduino IDE
*   
*   MCP4725 ADC kezelese
*   
********************************************************************************
* 
*      NANO          MCP4725    
*    -------+      +----------+  
*           !      !          !  
*       GND +--  --+ GND  GND +--
*       VCC +--  --+ VCC  OUT +--
*        A5 +--  --+ SCL      !
*        A4 +--  --+ SDA      !
*        D7 +--  --+ A0       !
*           !      !          !
*           !      !          !
*           !      +----------+
* 
* 
*******************************************************************************/

#include "Arduino.h"
#include "Wire.h"


class kt_mcp4725
{
   public:
   kt_mcp4725( byte cs)    { chip_select_pin= cs; };
   byte begin( void);
   void set( uint16_t v)   { fast_write( v& 0x0FFF); };
   void down( void)        { fast_write( 0x3000); };
   private:
   byte chip_select_pin;
   byte fast_write( uint16_t);
};


byte kt_mcp4725::begin( void)
{
   Wire.begin();
   if( chip_select_pin)
   {
      pinMode( chip_select_pin, OUTPUT);
      digitalWrite( chip_select_pin, HIGH);   
   } 
   return fast_write( 0);                        // 0 - ok
}


byte kt_mcp4725::fast_write( uint16_t v)
{
   byte a;
   if( chip_select_pin) digitalWrite( chip_select_pin, LOW);   
   Wire.beginTransmission( 0x60);                // address
   Wire.write( (byte)(( v & 0xFF00) >> 8));      // high byte
   Wire.write( (byte)(  v & 0x00FF));            // low byte
   a= Wire.endTransmission();
   if( chip_select_pin) digitalWrite( chip_select_pin, HIGH);   
   return a;                                     // 0 - ok
}


uint16_t i;                                      // for saw sign
kt_mcp4725 dac7= kt_mcp4725( 7);


void setup()
{
   Serial.begin( 9600);
   Serial.println( "Start");
   if( dac7.begin()) Serial.println( "Dac7 not ready!");
   dac7.set( 500);
   Serial.println( "End");
}


void loop()
{
//   // saw sign
//   i= 0x1000;
//   while( i--) dac7.set( i);
}

Itt a vége, fuss el véle.