Vlad Mihai Postat Iunie 27, 2015 Partajează Postat Iunie 27, 2015 Buna ziua, Lucrez la o aplicatie cu FPGA (Xilinx) care imi trimite niste date pe serial in LabVIEW. Datele respective vreau sa le plotez in timp real atunci cand porneste placa cu FPGA. M-am gandit la un montaj mic cu arduino si DS1307 si care sa transform cumva sa imi dea numarul de secunde in loc de timp in ore minute si secunde. Intrebarea mea, se poate face asa ceva cu acest DS1307? Ma intereseaza sa fie cat mai precis datele privind informatia de timp. Multumesc de raspuns! Ps: sunt deschis si la alte solutii. Link spre comentariu
Mircea Postat Iunie 27, 2015 Partajează Postat Iunie 27, 2015 Zic si eu, cu toate ca nu cred ca am inteles 100% problema ta. De ce? Pai pui o intrebare si ai raspunsul in textul intrebarii.1. Fpga trimite un semnal la Arduino cand a pornit.2. Arduino incepe sa puna secunde (stii cum transformi ore/minute in secunde) intr-un contor.3. Transferi contorul in Fpga cat de des ai nevoie.4. Fpga decide sa se opreasca. Arduino goleste contorul si asteapta un alt semnal de pornire de la Fpga.PS: nu poti lega DS direct la Fpga? DS va fi mereu ON sau il resetezi la fiecare pornire Fpga, nu conteaza. Link spre comentariu
mars01 Postat Iunie 27, 2015 Partajează Postat Iunie 27, 2015 (editat) Salut, Daca ai nevoie de o acuratete mare atunci nu folosi DS1307. Decat sa utilizezi DS1307, poti folosi un Arduino care are cuartz (nu rezonator ceramic) cu functia millis(). Eventual foloseste DS3231 care este mult mai precis decat DS1307. Un exemplu pentru Arduino folosind functia millis(): /* Whenever NSTROBE signal becomes LOW, Arduino will start counting seconds in variable 'sec_count' When NSTROBE signal becomes HIGH, Arduino will send the value of the variable 'sec_count' via UART (but only if NSTROBE was previously at least once LOW) and then will clear the counting variable.*/#define NSTROBE 7 // define the NSTROBE signal on pin 7 of the Arduinounsigned long sec_count = 0; // variable to count the secondsunsigned long now; // variable to store the current timeuint8_t flag = 0; // variable used to assure that we have values sent to PC only after at least one NSTROBE active casevoid setup(){ pinMode(NSTROBE, INPUT_PULLUP); // declare NSTROBE as INPUT and it activates the input pullup for noise imumnity on the NSTROBE line Serial.begin(115200); // init of the UART library }void loop(){ now = millis(); // store the current time while (1) { if (!digitalRead(NSTROBE)) { if ((millis() - now) >= 1000) { sec_count++; // increment the seconds counter variable // cli(); // disable interrupts now = millis(); // store the current time as a value to be used in the next loop // sei(); // enable interrupts flag = 1; } } else { if ((Serial.available() == 1) && (flag == 1)) { flag = 0; Serial.println(sec_count); // send the values to PC sec_count = 0; } } }} Editat Iunie 27, 2015 de mars01 Link spre comentariu
mars01 Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 (editat) Un alt exemplu pentru Arduino (AVR) folosing intreruperi, port manipulation si fara functiile clasice setup() si loop(). Am introdus si un blink cu LED-ul de pe pinul 13. Perioada este de 2sec, 1sec ON, 1sec OFF. Acest semnal se poate folosi pentru a spune FPGA-ului cand s-a terminat o secunda. Poate sa apara o eroare de - 1secunda functie de cand semnalul de control NSTROBE de pe pinul 7 Arduino devine HIGH (inactiv). /* Whenever NSTROBE signal (pin 7 on Arduino) becomes LOW, Arduino will start counting seconds in variable 'sec_count'When NSTROBE signal becomes HIGH, Arduino will send the value of the variable 'sec_count' via UART(but only if NSTROBE was previously at least once LOW)and then will clear the counting variable.*//* The ENABLED and DISABLED states are used to make sure that we enable/disable the TIMER1 only there was a change in the TIMER1 state.*/#define DISABLED 0#define ENABLED 1#include <utildelay.h>#include <HardwareSerial.h>volatile unsigned long sec_count = 0; // variable to count the secondsuint8_t flag = 0; // variable used to assure that we have values sent to PC only after at least one NSTROBE active caseboolean last_state = false;boolean toggle = 1;char buf[10]; // buffer to store the seconds as stringvoid init(){ cli(); // disable interrupts PORTD |= (1 << PD7); // activates the input pullup for noise imunity on the NSTROBE line (pin 7 on Arduino) DDRD &= ~(1 << PD7); // declare NSTROBE as INPUT //set-up the built in LED to change state on every 1" - this means 1" is ON, 1" is OFF DDRB |= (1 << PB5); // AVR pin PB5 (pin 13 Arduino, the one with the built in LED) set as OUTPUT PORTB &= ~(1 << PB5); // LED OFF Serial.begin(115200); // init of the UART library //timer 1 setup CTC interrupt every 1" TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 15624; // ((16*10^16) / 1024) - 1 = 15624 // 1024 is the used prescaler}ISR(TIMER1_COMPA_vect){ sec_count++; if (toggle == 1) { PORTB |= (1 << PB5); // LED ON toggle = 0; } else { PORTB &= ~(1 << PB5); // LED OFF toggle = 1; }}int main(){ init(); while (1) { if (!(PIND & (1 << PD7))) // read the NSTROBE pin { _delay_ms(10); // a little debouncing for noise immunity if (!(PIND & (1 << PD7))) { if (last_state == DISABLED) { toggle = 1; // ensure that at every TIMER1 start the LED will start as ON TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS12) | (1 << CS10); // set CTC mode and set PRESCALER to 1024 TIMSK1 |= (1 << OCIE1A); // enable TIMER1 in CTC mode sei(); last_state = ENABLED; } flag = 1; } } else { _delay_ms(10); // a little debouncing for noise immunity if ((PIND & (1 << PD7))) // read the NSTROBE pin { if (last_state == ENABLED) { TCCR1B = 0; // disable TIMER1 while NSTROBE is inactive last_state = DISABLED; } PORTB &= ~(1 << PB5); // the LED stays OFF while TIMER1 is disabled if (flag == 1) // this flag assure that there will be data transmission only when we have what to transmit { itoa(sec_count, buf,10); // more RAM used - 10 bytes, less FLASH than using directly Serial.print(sec_count) Serial.println(buf); // send the values to PC sec_count = 0; // clear second counter } flag = 0; } } } return 0;} Editat Iunie 28, 2015 de mars01 Link spre comentariu
mars01 Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 (editat) Si ca sa ma joc, un exemplu in care nu se mai foloseste nici-o functie buit-in a Arduino ceea ce face programul sa fie mult mai rapid. Nu am implementat toata comunicatia UART, doar partea de transmisie. Memoria FLASH ocupata s-a redus la mai mult de jumatate (960bytes) fata de variantele anterioare iar cea SRAM este ocupata (36 bytes) de cca 6 ori mai putin. /* NOTE: the UART TX as implemented here works only for ATMEGA328P and the like (Arduino Uno, Arduino Mini Pro etc).*//* Whenever NSTROBE signal (pin 7 on Arduino) becomes LOW, Arduino will start counting seconds in variable 'sec_count'When NSTROBE signal becomes HIGH, Arduino will send the value of the variable 'sec_count' via UART(but only if NSTROBE was previously at least once LOW)and then will clear the counting variable.*//* The ENABLED and DISABLED states are used to make sure that we enable/disable the TIMER1 only there was a change in the TIMER1 state.*/#include <utildelay.h>#include <avrinterrupt.h>#define DISABLED 0#define ENABLED 1// defines for UART TX communication#define UART0_STATUS UCSR0A#define UART0_CONTROL UCSR0B#define UART0_DATA UDR0#define UART0_UDRIE UDRIE0#define UART0_TX_BUFFER_SIZE 16#define UART0_TX_BUFFER_MASK ( UART0_TX_BUFFER_SIZE - 1)#define UART_BAUD_SELECT(baudrate) (((F_CPU)/(baudrate*16L))-1)// end// variable declaration for UART TX communicationstatic volatile unsigned char UART_TxBuf[UART0_TX_BUFFER_SIZE];static volatile unsigned char UART_TxHead;static volatile unsigned char UART_TxTail;// end // UART interrupt functionISR(USART_UDRE_vect){ unsigned char tmptail; if (UART_TxHead != UART_TxTail) { /* calculate and store new buffer index */ tmptail = (UART_TxTail + 1) & UART0_TX_BUFFER_MASK; UART_TxTail = tmptail; /* get one byte from buffer and write it to UART */ UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */ } else{ /* tx buffer empty, disable UDRE interrupt */ UART0_CONTROL &= ~(1 << UART0_UDRIE); }}// end// UART TX communication init functionvoid Serial_init(unsigned long baudrate){ UART_TxHead = 0; UART_TxTail = 0; UBRR0H = (unsigned char)((UART_BAUD_SELECT(baudrate)) >> 8); UBRR0L = (unsigned char)UART_BAUD_SELECT(baudrate); UART0_CONTROL = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0); UCSR0C = (1 << USBS0) | (3 << UCSZ00);}// end// UART TX communication function for one char write to UARTvoid Serial_write(unsigned char data){ unsigned char tmphead; tmphead = (UART_TxHead + 1) & UART0_TX_BUFFER_MASK; while (tmphead == UART_TxTail){ ;/* wait for free space in buffer */ } UART_TxBuf[tmphead] = data; UART_TxHead = tmphead; /* enable UDRE interrupt */ UART0_CONTROL |= (1 << UART0_UDRIE);}// end// UART TX communication function for writing strings followed by New line to UARTvoid Serial_println(char *string){ while (*string != '0') Serial_write(*string++); // write char's to UART parsing the string until find the 'end of string' char Serial_write(13); // write a 'CR' char to UART Serial_write(10); // write a 'new line' char to UART}// endvolatile unsigned long sec_count = 0; // variable to count the secondsuint8_t flag = 0; // variable used to assure that we have values sent to PC only after at least one NSTROBE active caseboolean last_state = false;boolean toggle = 1;char buf[10]; // buffer to store the seconds as stringvoid init(){ cli(); // disable interrupts PORTD |= (1 << PD7); // activates the input pullup for noise imunity on the NSTROBE line (pin 7 on Arduino) DDRD &= ~(1 << PD7); // declare NSTROBE as INPUT //set-up the built in LED to change state on every 1" - this means 1" is ON, 1" is OFF DDRB |= (1 << PB5); // AVR pin PB5 (pin 13 Arduino, the one with the built in LED) set as OUTPUT PORTB &= ~(1 << PB5); // LED OFF Serial_init(115200); // init of the UART library //timer 1 setup CTC interrupt every 1" TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 15624; // ((16*10^16) / 1024) - 1 = 15624 // 1024 is the used prescaler}ISR(TIMER1_COMPA_vect){ sec_count++; if (toggle == 1) { PORTB |= (1 << PB5); // LED ON toggle = 0; } else { PORTB &= ~(1 << PB5); // LED OFF toggle = 1; }}int main(){ init(); while (1) { if (!(PIND & (1 << PD7))) // read the NSTROBE pin { _delay_ms(20); // a little debouncing for noise immunity if (!(PIND & (1 << PD7))) { if (last_state == DISABLED) { toggle = 1; // ensure that at every TIMER1 start the LED will start as ON TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS12) | (1 << CS10); // set CTC mode and set PRESCALER to 1024 TIMSK1 |= (1 << OCIE1A); // enable TIMER1 in CTC mode sei(); last_state = ENABLED; } flag = 1; } } else { _delay_ms(20); // a little debouncing for noise immunity if ((PIND & (1 << PD7))) // read the NSTROBE pin { if (last_state == ENABLED) { TCCR1B = 0; // disable TIMER1 while NSTROBE is inactive last_state = DISABLED; } PORTB &= ~(1 << PB5); // the LED stays OFF while TIMER1 is disabled if (flag == 1) // this flag assure that there will be data transmission only when we have something to transmit { ltoa(sec_count, buf,10); // convert the number in long type into a string Serial_println(buf); // send the values to PC sec_count = 0; // clear 'seconds' counter } flag = 0; } } } return 0;} Editat Iunie 28, 2015 de mars01 Link spre comentariu
mars01 Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 (editat) Si daca vrei sa salvezi pe PC secundele in format CSV (comma separated values) tot ce trebuie sa faci este sa modifici functia: // UART TX communication function for writing strings followed by New line void Serial_println(char *string){ while (*string != '0') Serial_write(*string++); Serial_write(13); Serial_write(10);}// end in acest fel: // UART TX communication function for writing strings followed by ','void Serial_println(char *string){ while (*string != '0') Serial_write(*string++); Serial_write(',');}// end Editat Iunie 28, 2015 de mars01 Link spre comentariu
Vlad Mihai Postat Iunie 28, 2015 Autor Partajează Postat Iunie 28, 2015 Salut si multumesc de raspunsuri, @thunderer, sa conectez DS-ul la fpga e complicat din punct de vedere al programarii, de asta am ales sa il conectez la arduino. In principiu am nevoie de un counter care sa imi numere secundele foarte precis atunci cand primeste un semnal pe un pin si sa transmita la fiecare secunda daca se poate informatia de timp in pc, fie direct pe serial sau fie prin FPGA si apoi pe serial in pc. @mars01 multumesc mult de coduri si propuneri, o sa le studiez atent si o sa revin cu detalii, Toate cele bune, Vlad Link spre comentariu
Mircea Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 O baza de timp pe 1 secunda ar ajuta? FPGA-ul va face contorizarea in functie de cand vrea el sa citeasca. Sau ar fi declansatorul pentru baza de timp, daca nu vrei ruleze mereu (ar fi bine sa ruleze mereu pentru stabilitate). Link spre comentariu
mars01 Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 (editat) Vlad, daca vrei sa trimiti datele de la Arduino la FPGA, in principiu le poti trimite si paralel. Arduino are 20 de GPIO din care scazi unul pentru semnalul de STROBE si ramai cu 19 pini pe care poti trimite paralel informatia cu numarul de secunde. Dar acest lucru te limiteaza la un numar maxim de 2^19 secunde. Adica 524288 secunde (~ 8738 minute, ~145 ore). Sau trimiti pe bucati informatia (folosesti de ex 8 GPIO si trimiti intai primii 8 biti, apoi urmatorii 8 biti si tot asa). Dar din putinul care il stiu despre FPGA (e in plan o familiarizare cat de curand) serializarea pe FPGA este mai complicata. Solutia oferita de @thunderer este mult mai fezabila daca intentionezi sa pui FPGA-ul sa numere. Nu stiu in ce masura se poate, dar teoretic cu divizari multiple ai putea ca din clock-ul FPGA-ului sa scoti un semnal de 1Hz cu care sa incrementezi un numarator construit tot in FPGA. In felul acesta ramai cu totul la nivelul FPGA-ului, te bazazi pe caracteristica sa principala: paralelismul. Editat Iunie 28, 2015 de mars01 Link spre comentariu
Mircea Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 Nu exclud optiunea bazei de timp externe, la asta m-am gandit initial. Asta ar permite Fpga sa faca si alte operatii, inclusiv un "sleep". Link spre comentariu
mars01 Postat Iunie 28, 2015 Partajează Postat Iunie 28, 2015 (editat) Pai in cazul acesta 15 bistabili D din FPGA cascadati ii pot scoate o frecventa de 1Hz dintr-un oscilator TXCO de 32768 Hz. Iesirea din astia 15 bistabili, adica semnalul de 1Hz poate sa intre intr-un numarator 24bit (adica alti 24 bistabili D), numarator care poate numara pana la 16.777.216, echivalent la ~194zile, care ar trebuie sa fie suficient pentru aplicatii de-ale fizicienilor. Mai complicat o sa fie realizarea modulului UART in FPGA. Desi la o simpla cautare pe GOOGLE, a aparut asta: https://github.com/pabennett/uart Si daca imparti cei 24biti in 3 grupe (shift la dreapta si AND cu o masca 0x0FF) pe care le trimiti succesiv va trebui sa faci decodarea dupa receptia la PC. Un link interesant este aici: http://www.edaboard.com/thread167139.html BTW, ai vazut placuta asta, Papilio Duo? Are un FPGA cu un Arduino pe bottom layer (un ATMEGA32). Dar sa termin cu offtopic-ul (topic Arduino si nu FPGA). Editat Iunie 28, 2015 de mars01 Link spre comentariu
Vlad Mihai Postat Iunie 29, 2015 Autor Partajează Postat Iunie 29, 2015 Salut, tocmai de asta nu am vrut sa fac acest counter in FPGA, e complicat la programat. Prefer totusi sa incerc ceva cu arduino......FPGA-ul deja are multicele pe el (o comunicatie diferentiala bidirectionala, un serial mai complex, un counter local, niste buffere etc....)... Multumesc pentru timp si raspunsuri! Se pare ca sunt si fani FPGA pe acest forum, pe mine m-au cucerit de cand am inceput sa implementez hardware pentru servici o placa cu Kintex 7, iar acum am o placa de dezvoltare cu SPARTAN 6, NEXYS 3,Momentan astept sa prind o scoala de vara pe FPGA preferabil in afara ca sa invat cate ceva. Link spre comentariu
digix Postat Iunie 29, 2015 Partajează Postat Iunie 29, 2015 DS3231 pe pinul INT/SQW, poate genera, dupa cum este programat, o intrerupere la intervale exacte de timp incepand de la 1secunda pana la o data din viitor. Detalii in datasheet, tabelul din pagina 11. L-am folosit cu succes pentru generarea unei intreruperi care scoate din sleep mode un arduino folosit ca data logger, alimentat pe baterii, la fiecare 15minute. In plus, tot din DS3231 imi iau data si temperatura pentru esantion. Link spre comentariu
mars01 Postat Iunie 29, 2015 Partajează Postat Iunie 29, 2015 (editat) Sigur, dar in mod default genereaza 8192Hz (cei doi biti de configurare sunt 1 la power-up) pe acel pin. Lucru care necesita o configurare la power-up pentru a scoate acel 1Hz, deci un controller pentru ca ar fi mai complicat sa pui sa faca FPGA-ul acest lucru (ar mai trebui creat un IP cu functia de I2C cu tot bla bla-ul). Si ne intoarcem la Arduino in acest fel. Care Arduino s-ar putea sa ofere de unul singur acel 1Hz cu precizia necesara. In varianta utilizarii FPGA ar putea fi folosita iesirea care genereaza cei 32768Hz (default la power-up) avand in vedere ca DS3231 contine un TXCO foarte precis, care are si compensare functie de temperatura. Editat Iunie 29, 2015 de mars01 Link spre comentariu
digix Postat Iunie 29, 2015 Partajează Postat Iunie 29, 2015 Este clar ca DS3231 trebuie setat ca data, tip alarma ...cu un arduino o singura data la prima pornire. Apoi poate functiona independent, in modul setat, pe o baterie CR2032 mult si bine. Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum