Zbernica SPI: D/A prevodník MCP4812: Rozdiel medzi revíziami
Zo stránky SensorWiki
Vytvorená stránka „Záverečný projekt predmetu MIPS / LS2026 - '''Meno Priezvisko''' == Zadanie == Mojou úlohou bolo pracovať so vstupmi vo forme tlačidiel a na základe ich postupného stláčania vytvoriť sekvenciu, ktorú systém vyhodnocuje. Program sleduje poradie stlačených tlačidiel a po zadaní celej sekvencie ho porovná s vopred definovaným správnym kódom. V prípade správneho zadania sa rozsvieti žltá LED dióda, pri nesprávnom zadaní sa rozsvieti červ…“ |
Bez shrnutí editace |
||
| (6 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
| Riadok 1: | Riadok 1: | ||
Záverečný projekt predmetu MIPS / LS2026 - ''' | Záverečný projekt predmetu MIPS / LS2026 - '''Jakub Milošev''' | ||
== Zadanie == | == Zadanie == | ||
Navrhnúť a realizovať program pre Arduino ATmega328P, ktorý komunikuje s D/A prevodníkom MCP4812. Program má umožniť zadávanie celých čísel v rozsahu 0 až 4 prostredníctvom sériovej komunikácie (PuTTY). Po zadaní hodnoty sa na výstupe D/A prevodníka vytvorí analógové napätie zodpovedajúce zadanému číslu v rozsahu 0 V až 4 V. | |||
[[Obrázok:ard.jpg|500px|thumb|center|Vývojová doska ACROB.]] | [[Obrázok:ard.jpg|500px|thumb|center|Vývojová doska ACROB.]] | ||
'''Literatúra:''' | '''Literatúra:''' | ||
* [ | * [https://ww1.microchip.com/downloads/en/devicedoc/20002249b.pdf Datasheet k MCP4812] | ||
| Riadok 17: | Riadok 16: | ||
== Analýza a opis riešenia == | == Analýza a opis riešenia == | ||
Najprv sme museli ísť do datasheetu prevodníka na dozvedenie informácii ako koľko bitový je, čo jednotlivé bity robia. | |||
[[Súbor: | [[Súbor:Jednotlive_bity_MCP4812.jpg|400px|thumb|center|Pohľad na jednotlivé bity]] | ||
A/B sme nastavili ako 0 aby sme vybrali výstup A (VoutA). GA sme nastavili ako 0 aby sme mali 2 násobok napätia Vref (2*Vref=4,096) a mohli sme sa pohybovať v rozpätí 0 až 4 V. Ako posledné sme nastavili hodnotu SHDN na 1, lebo tým sa prevodník zapne. | |||
Piny prevodníka. | |||
[[Súbor:Obsadenie_pinov_MCP4812.jpg|400px|thumb|center|Jednotlivé piny prevodníka]] | |||
=== Algoritmus a program === | [[Súbor:Popis_pinov_MCP4812.jpg|400px|thumb|center|Popis pinov prevodníka]] | ||
== Schéma zapojenia == | |||
Podľa datasheetu samotnej dosky a obrázka vyššie sme prepojili pin CS s pinom SS (PB2), pin SCK s pinom SCK (PB5) a pin SDI s pinom MOSI (PB3). Piny VSS a LDAC boli pripojené na zem (GND). Pin LDAC bol pripojený na GND, aby sa výstup prevodníka automaticky aktualizoval po prijatí novej hodnoty bez potreby dodatočného impulzu. | |||
[[Súbor:Schema_zapojenia_MCP4812.jpg|400px|thumb|center|Schéma zapojenia.]] | |||
== Algoritmus a program == | |||
Ako prvé sa spustí UART (oba sú totožné z UARTami z cvík) čo umožní komunikáciu s PuTTY. Potom sa spustí SPI kde sa nastavia piny PB3, PB5 a PB2 ako výstupy a CS pin nastaví na HIGH čo znamená že prevodník zatiaľ nekomunikuje. | |||
Ďalej program prejde do while slučky kde čaká na znak z PuTTY. Funkcia uart_getc() čaká na prijatie znaku z PuTTY a následne ho uloží do premennej prijate (if skontroluje či je daný znak číslo od 0 do 4). | |||
Program skontroluje či je teda to číslo od 0 do 4 a následne ho prevedie z ASCII na číslo odčítaním ‘0‘ napríklad ‘3‘ - ‘0‘ = 3 a uloží ho do premennej hodnota. | |||
Hodnota sa následne vynásobí 1024 a vydelí referenčnou hodnotou napätia 4,096, a uloží sa do premennej vysledok (napríklad pre 3 je výsledok 750 túto hodnotu si už prevodník prevedie na napätie). | |||
Výsledok sa pošle do funkcie DAC_write kde sa poskladá 16 bitový príkaz. Výsledok sa posunie o 2 bity doľava a pomocou OR sa vloží do command. Výsledný príkaz obsahuje v horných 4 bitoch konfiguráciu a v zvyšných bitoch dáta. | |||
CS pin sa nastaví na LOW čím prevodník začne očakávať hodnoty. Príkaz sa rozdelý na 2 byty horný byte sa pošle ako prvý do SPI_send kde sa zapíše do registra SPDR. Program čaká kým sa odosielanie dokončí pomocou while slučky ktorá kontroluje bit SPIF v registri SPSR aby sa náhodou neprepísala správna hodnota. Potom sa rovnako pošle dolný byte (Keďže naše arduino umožňuje prenášať iba 8 bitov naraz, 16 bitový príkaz je potrebné rozdeliť na horný a dolný byte). Po odoslaní oboch bytov sa CS nastaví na HIGH čím sa komunikácia ukončí. | |||
Prevodník následne poskladá oba prijaté byty späť do 16 bitového príkazu, skontroluje konfiguračné bity a dátové bity, a nastaví napätie na VoutA. | |||
Ako potvrdenie program vypíše do PuTTY Nastavena hodnota: 3V a vráti sa na začiatok while slučky. | |||
<tabs> | <tabs> | ||
<tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | <tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | ||
#include <avr/io.h> | |||
#define F_CPU 16000000UL | |||
#include <avr/io.h> | |||
#include "uart.h" | |||
void SPI_init(void) | |||
{ | |||
DDRB |= (1 << PB3) | (1 << PB5) | (1 << PB2); //nastavenie vystupov jednotlivych pinov | |||
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); | |||
PORTB |= (1 << PB2); | |||
} | |||
// Funkcia na odoslanie 1 bytu cez SPI | |||
void SPI_send(uint8_t data) | |||
{ | |||
// Zapise data do SPI registra | |||
SPDR = data; | |||
while (!(SPSR & (1 << SPIF))); // caka na skoncenie odosielania | |||
} | |||
void DAC_write(uint16_t vysledok) | |||
{ | |||
uint16_t command; | |||
command = 0b0001000000000000; //príkaz z datasheetu | |||
// Posunutie 10-bit dat na spravne miesto | |||
command |= (vysledok << 2); | |||
PORTB &= ~(1 << PB2); | |||
SPI_send(command >> 8); | |||
SPI_send(command & 0xFF); | |||
PORTB |= (1 << PB2); | |||
} | |||
int main(void) | int main(void) | ||
{ | { | ||
uart_init(); | |||
SPI_init(); | |||
char prijate; | |||
uint8_t hodnota; | |||
uint16_t vysledok; | |||
while (1) | |||
{ | |||
prijate = uart_getc(); | |||
if(prijate >= '0' && prijate <= '4') | |||
{ | |||
hodnota = prijate - '0'; | |||
// Prevod napatia na DAC hodnotu | |||
vysledok = (hodnota) * 250; //250=1024/4.096 | |||
// Zapis hodnoty do DAC | |||
DAC_write(vysledok); | |||
// Vypis textu do Putty | |||
uart_puts("Nastavena hodnota: "); | |||
uart_putc(prijate); | |||
uart_puts("V\n"); | |||
} | |||
} | |||
} | } | ||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
</tabs> | </tabs> | ||
Zdrojový kód: [[Médiá: | Zdrojový kód: [[Médiá:ProjektJakubMilosev.zip|ProjektJakubMilosev.zip]] | ||
== Overenie == | |||
Program sme otestovali zapojením vyššie uvedenej schémy. Zapisovali sme do PuTTY rôzne čísla od 0 do 4 a sledovali sme výstup prevodníka pomocou multimetru kde ukazovalo správne hodnoty. | |||
[[Súbor: | [[Súbor:Zapojenie_MCP4812_multimeter.jpg|400px|thumb|center|Zapojenie]] | ||
'''Video:''' | '''Video:''' | ||
<center><youtube> | <center><youtube>https://youtube.com/shorts/HvP1taYB4XY?feature=share</youtube></center> | ||
== Čo by som urobil inak == | == Čo by som urobil inak == | ||
Namiesto zadávania iba celých čísel 0 až 4 by som umožnil zadávanie desatinných hodnôt pre lepšie využitie celého výstupného napätia prevodníka. | |||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] | ||
Aktuálna revízia z 14:34, 6. jún 2026
Záverečný projekt predmetu MIPS / LS2026 - Jakub Milošev
Zadanie
Navrhnúť a realizovať program pre Arduino ATmega328P, ktorý komunikuje s D/A prevodníkom MCP4812. Program má umožniť zadávanie celých čísel v rozsahu 0 až 4 prostredníctvom sériovej komunikácie (PuTTY). Po zadaní hodnoty sa na výstupe D/A prevodníka vytvorí analógové napätie zodpovedajúce zadanému číslu v rozsahu 0 V až 4 V.

Literatúra:
Analýza a opis riešenia
Najprv sme museli ísť do datasheetu prevodníka na dozvedenie informácii ako koľko bitový je, čo jednotlivé bity robia.

A/B sme nastavili ako 0 aby sme vybrali výstup A (VoutA). GA sme nastavili ako 0 aby sme mali 2 násobok napätia Vref (2*Vref=4,096) a mohli sme sa pohybovať v rozpätí 0 až 4 V. Ako posledné sme nastavili hodnotu SHDN na 1, lebo tým sa prevodník zapne.
Piny prevodníka.


Schéma zapojenia
Podľa datasheetu samotnej dosky a obrázka vyššie sme prepojili pin CS s pinom SS (PB2), pin SCK s pinom SCK (PB5) a pin SDI s pinom MOSI (PB3). Piny VSS a LDAC boli pripojené na zem (GND). Pin LDAC bol pripojený na GND, aby sa výstup prevodníka automaticky aktualizoval po prijatí novej hodnoty bez potreby dodatočného impulzu.

Algoritmus a program
Ako prvé sa spustí UART (oba sú totožné z UARTami z cvík) čo umožní komunikáciu s PuTTY. Potom sa spustí SPI kde sa nastavia piny PB3, PB5 a PB2 ako výstupy a CS pin nastaví na HIGH čo znamená že prevodník zatiaľ nekomunikuje.
Ďalej program prejde do while slučky kde čaká na znak z PuTTY. Funkcia uart_getc() čaká na prijatie znaku z PuTTY a následne ho uloží do premennej prijate (if skontroluje či je daný znak číslo od 0 do 4).
Program skontroluje či je teda to číslo od 0 do 4 a následne ho prevedie z ASCII na číslo odčítaním ‘0‘ napríklad ‘3‘ - ‘0‘ = 3 a uloží ho do premennej hodnota.
Hodnota sa následne vynásobí 1024 a vydelí referenčnou hodnotou napätia 4,096, a uloží sa do premennej vysledok (napríklad pre 3 je výsledok 750 túto hodnotu si už prevodník prevedie na napätie).
Výsledok sa pošle do funkcie DAC_write kde sa poskladá 16 bitový príkaz. Výsledok sa posunie o 2 bity doľava a pomocou OR sa vloží do command. Výsledný príkaz obsahuje v horných 4 bitoch konfiguráciu a v zvyšných bitoch dáta.
CS pin sa nastaví na LOW čím prevodník začne očakávať hodnoty. Príkaz sa rozdelý na 2 byty horný byte sa pošle ako prvý do SPI_send kde sa zapíše do registra SPDR. Program čaká kým sa odosielanie dokončí pomocou while slučky ktorá kontroluje bit SPIF v registri SPSR aby sa náhodou neprepísala správna hodnota. Potom sa rovnako pošle dolný byte (Keďže naše arduino umožňuje prenášať iba 8 bitov naraz, 16 bitový príkaz je potrebné rozdeliť na horný a dolný byte). Po odoslaní oboch bytov sa CS nastaví na HIGH čím sa komunikácia ukončí.
Prevodník následne poskladá oba prijaté byty späť do 16 bitového príkazu, skontroluje konfiguračné bity a dátové bity, a nastaví napätie na VoutA.
Ako potvrdenie program vypíše do PuTTY Nastavena hodnota: 3V a vráti sa na začiatok while slučky.
#define F_CPU 16000000UL
#include <avr/io.h>
#include "uart.h"
void SPI_init(void)
{
DDRB |= (1 << PB3) | (1 << PB5) | (1 << PB2); //nastavenie vystupov jednotlivych pinov
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
PORTB |= (1 << PB2);
}
// Funkcia na odoslanie 1 bytu cez SPI
void SPI_send(uint8_t data)
{
// Zapise data do SPI registra
SPDR = data;
while (!(SPSR & (1 << SPIF))); // caka na skoncenie odosielania
}
void DAC_write(uint16_t vysledok)
{
uint16_t command;
command = 0b0001000000000000; //príkaz z datasheetu
// Posunutie 10-bit dat na spravne miesto
command |= (vysledok << 2);
PORTB &= ~(1 << PB2);
SPI_send(command >> 8);
SPI_send(command & 0xFF);
PORTB |= (1 << PB2);
}
int main(void)
{
uart_init();
SPI_init();
char prijate;
uint8_t hodnota;
uint16_t vysledok;
while (1)
{
prijate = uart_getc();
if(prijate >= '0' && prijate <= '4')
{
hodnota = prijate - '0';
// Prevod napatia na DAC hodnotu
vysledok = (hodnota) * 250; //250=1024/4.096
// Zapis hodnoty do DAC
DAC_write(vysledok);
// Vypis textu do Putty
uart_puts("Nastavena hodnota: ");
uart_putc(prijate);
uart_puts("V\n");
}
}
}
Zdrojový kód: ProjektJakubMilosev.zip
Overenie
Program sme otestovali zapojením vyššie uvedenej schémy. Zapisovali sme do PuTTY rôzne čísla od 0 do 4 a sledovali sme výstup prevodníka pomocou multimetru kde ukazovalo správne hodnoty.

Video:
Čo by som urobil inak
Namiesto zadávania iba celých čísel 0 až 4 by som umožnil zadávanie desatinných hodnôt pre lepšie využitie celého výstupného napätia prevodníka.