Offline
Newbie
Karma: 0
Posts: 12
|
 |
« on: May 02, 2012, 08:33:46 am » |
Bonjour, Voici un générateur de fréquence de 30hz à 8Mhz qui se pilote par deux boutons poussoir et un potentiomètre de 1k il peut être piloté par la liaison série, et dispose d'un afficheur deux lignes. En espérant que sa peut aider pour un projet. #include <LiquidCrystal.h> int PRESCALER=0; int PRESC=0; int PCPResk; int plus=0; int moin=0; int plusa=0; int moina=0; float Frekpc=0; unsigned long Frek=0; unsigned long FREQ=0; unsigned long FOC=0; LiquidCrystal lcd(12, 10, 5, 4, 3, 2);
void setup() { Serial.begin(9600); lcd.begin(16, 2); pinMode(11, OUTPUT); //sortie fréquence pinMode(9, OUTPUT); //bouton poussoir pinMode(8, OUTPUT); //bouton poussoir //configuration timer //mise à zéro des registres TCCR2B = 0; TCCR2A = 0; TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/ ); TCCR2B = ( 1<<CS20 | 1<<CS22 | 1<<CS21 /* prescaler */); //valeur a compter dans tcnt2
//autorisation d'interruption ASSR &= ~(1 << AS2); // horloge interne Timer/Counter2 Serial.println("pour passer en mode commande pc"); Serial.println("définir une fréquence en hz et finir par un .");
} /***génération de fréquence par potentiomètre***/
void loop() { TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/ ); int OCR2 = analogRead(A0); //lecture du potentiomètre OCR2=OCR2/4; //résultat sur 1024 /4 pour 256 OCR2A=OCR2; plus = digitalRead(8); //lecture du bouton poussoir
if(plus !=plusa ){ //si changement d'état if(plus == HIGH ){ PRESCALER++; //sélection du prescaler suivant }
plusa = plus; //mise à zéro du changement d'état
}
if(PRESCALER > 6 ){ //maximum à ne pas dépasser PRESCALER = 6 ; }
moin = digitalRead(9); //lecture du bouton poussoir if(moin !=moina ){ //si changement d'état if(moin == HIGH ){ //et si passage a un PRESCALER--; //sélection du prescaler précédant } moina = moin; //mise à zéro du changement d'état } if(PRESCALER < 0 ){ //minimum à ne pas dépasser PRESCALER = 0 ; }
switch (PRESCALER) //sélection du prescaler { case 0: TCCR2B = ( 1<<CS20 | 1<<CS22 | 1<<CS21 ); PRESC = 1024; //valeur du prescaler break; case 1: TCCR2B = ( 1<<CS22 | 1<<CS21 ); PRESC = 256; //valeur du prescaler break; case 2: TCCR2B = ( 1<<CS20 | 1<<CS22 ); PRESC = 128; //valeur du prescaler break; case 3: TCCR2B = ( 1<<CS22 ); PRESC = 64; //valeur du prescaler break; case 4: TCCR2B = ( 1<<CS20 | 1<<CS21 ); PRESC = 32; //valeur du prescaler break; case 5: TCCR2B = ( 1<<CS21 ); PRESC = 8; //valeur du prescaler break; case 6: TCCR2B = ( 1<<CS20 ); PRESC = 1; //valeur du prescaler break; } /***foc= fcryst/(2*prescaler*(1+ocr)***/ OCR2=OCR2+1; //préparation au calcul de fréquence ci dessus FOC=long(OCR2)*long(PRESC)*2; //changement de type de variable et multiplication
FREQ=16000000/FOC; //division de la fréquence du cristal
aff(); //affichage sur l'écran lcd
delay(2); //petit délai pour la mesure analogique par sécurité if (Serial.available() > 0) { PCC(); } } /***affichage lcd***/
void aff(){ lcd.print("frequence"); lcd.setCursor(0, 1); lcd.print(FREQ); lcd.print("hz "); }
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #1 on: May 02, 2012, 08:35:21 am » |
/***sélection de fréquence par liaison série***/ void PCC(){ int FIN= 0; int j =8; int calc = 0; int tab; int Tab; int X; int selection = 0; int bp2=0; unsigned long U=1; do{ Frek = 0; Serial.println("définir une fréquence et finir par un ."); byte tableau[11] = {}; //tableau ou je vais mettre les valeurs do { //remplissage du tableau if (Serial.available() > 0) { //si des données entrantes sont présentes
tableau[j]= Serial.read(); //remplissage du tableau calc++; //incrémentation du nombre de case utilisées if (tableau[j]== '.') { //sortie si on reçois le point j=0; } j--; } }while(j>0); do{ Tab=calc-1; //ordre de passage tab = Tab-1; //nombre de passage while(tab>0) { U=U*10; //mise à niveau des centaines dizaines unités tab--; } j=8; //on commence à l'emplacement 7 du tableau ou se trouve la première donnée (et non pas 0) //création de la valeur do {
Frek = Frek+(tableau[j]-48)*U; //calcul de la fréquence, le -48 car il garde la désignation ascii U=U/10; //toujours les centaines dizaines unités j--; Tab--; }while(Tab>0); Serial.println(Frek); }while(FIN>0); //configuration timer //mise à zéros des registres TCCR2B = 0; TCCR2A = 0; if(Frek > 0 && Frek <= 400){ selection=1; } else if (Frek > 400 && Frek <= 1500){ selection=2; } else if (Frek > 1500 && Frek <= 3000){ selection=3; } else if (Frek > 3000 && Frek <= 6000){ selection=4; } else if (Frek > 6000 && Frek <= 13000){ selection=5; } else if (Frek > 13000 && Frek <= 50000){ selection=6; } else if (Frek > 50000 && Frek <= 8000000){ selection=7; } switch (selection) { //foc= fcryst/(2*prescaler*(1+ocr) calcul a appliquer //1+0cr = fcryst/(foc*presc) //ocr+1 //ocr-1=(foc*presc*2)/fcryst
case (1): //première plage de sélection TCCR2B = ( 1<<CS22 | 1<<CS21 | 1<<CS20 /* prescaler 111 1024*/); PCPResk=1024; PCCPR(); break;
case (2): TCCR2B = ( 1<<CS22 | 1<<CS21 /* prescaler 110 256*/); PCPResk=256; PCCPR(); break; case (3): TCCR2B = ( 1<<CS22 | 1<<CS20 /* prescaler 101 128*/); PCPResk=128; PCCPR(); break; case (4): TCCR2B = ( 1<<CS22 /* prescaler 100 64*/); PCPResk=64; PCCPR(); break; case (5): TCCR2B = ( 1<<CS21 | 1<<CS20 /* prescaler 011 32*/); PCPResk=32; PCCPR(); break; case (6): TCCR2B = ( 1<<CS21 /* prescaler 010 8*/); PCPResk=8; PCCPR(); break; case (7): TCCR2B = ( 1<<CS20 /* prescaler 001 1*/); PCPResk=1; PCCPR(); break; } Serial.println("pour sortir du mode commande pc"); Serial.println("envoyer un . en appuyant sur les 2"); Serial.println("bouton poussoir ou"); plus = digitalRead(8); //lecture du bouton poussoir moin = digitalRead(9); //lecture du bouton poussoir
if(plus == HIGH && moin == HIGH ){ //si les deux sont haut retour au mode manuel bp2 = 1; } }while(bp2 != 1); }
/***calcul de l'ocr***/
/***********calcul de l'ocr*************/
void PCCPR(){ int OCR2; TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/ ); Frekpc = (Frek*PCPResk*2); Frekpc = 16000000/Frekpc; Frekpc = --Frekpc; OCR2A=Frekpc; //calcul de l'ocr OCR2=OCR2A; OCR2=OCR2+1; //préparation au calcul de frequence FOC=long(OCR2)*long(PCPResk)*2; //changement de type de variable et multiplication FREQ=16000000/FOC; aff(); //afichage sur l'ecran lcd PCC(); //retour à la detection } avec un petit schéma
|
|
|
|
« Last Edit: May 09, 2012, 02:38:28 am by zelange »
|
Logged
|
|
|
|
|
Ile-de-France (92 sud), France
Offline
Edison Member
Karma: 22
Posts: 1817
|
 |
« Reply #2 on: May 02, 2012, 09:14:31 am » |
Merci de partager.
N'oublie pas que pour les gros sources, tu peux attacher directement le fichier (en bas de la zone de saisie du texte, "Advanced...")
|
|
|
|
|
Logged
|
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC# RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?
|
|
|
|
83 - var
Offline
Sr. Member
Karma: 0
Posts: 452
ARDUINO Powa !
|
 |
« Reply #3 on: May 02, 2012, 11:22:31 am » |
Merci de partage c'est utile ça je viens de voir un petit topic qui réclame sa justement !  Skizo !
|
|
|
|
|
Logged
|
Un tien vaux mieux que deux tu l'auras !
|
|
|
|
Offline
Edison Member
Karma: 6
Posts: 2423
|
 |
« Reply #4 on: May 02, 2012, 01:22:30 pm » |
Bonjour,
Voici un générateur de fréquence de 30hz à 8Mhz qui se pilote par deux boutons poussoir et un potentiomètre de 1k il peut être piloté par la liaison série, et dispose d'un afficheur deux lignes.
En espérant que sa peut aider pour un projet.
bonsoir interessant je l'ai testé rapidement sur uno avec le serial (pas de lcd ,pas de potentiometre et pas de poussoir) verif sur fréquencemètre sauf erreur de ma part, voilà ce que cela rend pour moi 500000 = ok 0.5Mhz 1000000 =0k 1Mhz 2000000 =ok 2Mhz 3000000 = Nok 4Mhz 4000000 = Ok 4Mhz 5000000 , 6000000,7000000 Nok = 8Mhz 8000000 = Ok 8Mhz
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #5 on: May 03, 2012, 01:12:26 am » |
oui c'est vraie je l'utilise sur un uno et j'ai se problème mais il viens justement du calcul qui permet de rentré une fréquence : foc= fcryst/(2*prescaler*(1+ocr) 1+0cr = fcryst/(foc*presc) ocr+1 ocr-1=(foc*presc*2)/fcryst en fait on obtient un chiffre à <,> mais le registre ocr ne peut pas le prendre en compte du coup il arrondie et sur les grosse fréquence c'est flagrant. Aprés on touche au fonctionnement des registres de timer, le prescaler lui décide de l'horloge interne et donc si tu met un prescaler de un tu obtient 8MHZ. Ton ocr lui est le nombre d’impulsion que doit compter le timer, donc si tu compte qu'une impulsion =>8MHZ -deux impulsions on tombe à 4 MHZ immédiatement il n'y auras pas d’intermédiaire. mais si quelqu'un à une idée je suis preneur 
|
|
|
|
« Last Edit: May 03, 2012, 01:14:03 am by zelange »
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 6
Posts: 2423
|
 |
« Reply #6 on: May 03, 2012, 06:30:16 am » |
oui c'est vraie je l'utilise sur un uno et j'ai se problème mais il viens justement du calcul qui permet de rentré une fréquence : foc= fcryst/(2*prescaler*(1+ocr) 1+0cr = fcryst/(foc*presc) ocr+1 ocr-1=(foc*presc*2)/fcryst en fait on obtient un chiffre à <,> mais le registre ocr ne peut pas le prendre en compte du coup il arrondie et sur les grosse fréquence c'est flagrant. Aprés on touche au fonctionnement des registres de timer, le prescaler lui décide de l'horloge interne et donc si tu met un prescaler de un tu obtient 8MHZ. Ton ocr lui est le nombre d’impulsion que doit compter le timer, donc si tu compte qu'une impulsion =>8MHZ -deux impulsions on tombe à 4 MHZ immédiatement il n'y auras pas d’intermédiaire. mais si quelqu'un à une idée je suis preneur  bonjour c'est donc ce que l'on appelle un generateur de frequence discrete. Il me semble aussi avoir vu des "aberrations" intermédiaires entre 2 valeurs OK, je regarderais ça plus tard. ce qui serait intéressant dans ton soft, ce serait de determiner la F° la plus proche de celle demandée et d'afficher le résultat par la fonction inverse. ça n’enlève rien à l'utilité de ta réalisation : lorsque l'on connait les limitations, il est plus simple d'integrer ensuite avec.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #7 on: May 04, 2012, 01:55:57 am » |
je vais plancher dessus, à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise et ne prend pas le calcul de fréquence à l'envers.
|
|
|
|
|
Logged
|
|
|
|
|
France
Offline
Edison Member
Karma: 12
Posts: 1801
There is an Arduino for that
|
 |
« Reply #8 on: May 04, 2012, 07:08:37 am » |
à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise Je ne vois pas pourquoi. Le problème viens de l'architecture des timers avec les prescalers. Il n'y a pas de pas possible entre 4MHz et 8MHz et ce quelque soit le mode d'entrée de la consigne. En fait plus tu approches de la fréquence de base de la chaine de comptage plus le pas est grossier. Pour pouvoir faire "toutes les fréquences" (toutes à prendre avec certaines réserves) il faut soit partir d'une fréquence très élevée (le principe de la synthèse digitale de fréquence DDS) soit utiliser une PLL. Cela dit, ça n'enlève rien à ton montage. Quand on connait ses limitations on peut l'utiliser sans problème.
|
|
|
|
« Last Edit: May 04, 2012, 07:10:37 am by fdufnews »
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 6
Posts: 2423
|
 |
« Reply #9 on: May 04, 2012, 07:13:39 am » |
je vais plancher dessus, à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise et ne prend pas le calcul de fréquence à l'envers.
bonjour je n'ai pas regardé le code, mais intuitivement la F° est generée par action sur les registres de l'arduino (scaler/prescaler, ...) , que l'action soit issue des BP et/ou d'une valeur ana, et/ou initialisée par le serial , c'est equivalent , tu dois donc toujours pouvoir "recalculer" la F° genérée en fonction de l'ecriture des registres ? edit : je viens de voir que fdufnews et moi convergeons presque synchrone à l'identique 
|
|
|
|
« Last Edit: May 04, 2012, 07:15:37 am by Artouste »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #10 on: May 04, 2012, 07:58:05 am » |
Se que je voulais dire c'est qu'il n'affiche pas 5mhz si on le règle entre les deux, il affiche la fréquence à partir de l'ocr et du prescaler tandis que par usb on peut demander 5mhz, et il affichera 5mhz même si il ne peut pas et qu'il est soit à 8 soit à 4...
J'ai mise à jour le programme, plus particulièrement la fonction PCCPR l'écran lcd affichera la bonne fréquence maintenant.
|
|
|
|
« Last Edit: May 09, 2012, 02:40:30 am by zelange »
|
Logged
|
|
|
|
|
KARUKERA 971
Offline
Newbie
Karma: 0
Posts: 3
|
 |
« Reply #11 on: May 12, 2012, 03:55:53 pm » |
Ca marche super ....  Je l'ai adapté pour l'utiliser avec un LCD Serial de Lextronic (avec interface Comfile ELCD pas compatible avec la librairie LiquidCrystal) sans problème.
|
|
|
|
« Last Edit: May 13, 2012, 05:28:21 pm by PhilippeFromGpe »
|
Logged
|
42 est la réponse
Décompresse en Hook2 et monster1100
|
|
|
|
|