IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques, systèmes et outils C Discussion :

Modification d'un firmware (je pense en C++) pour une radio commande


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre averti
    Homme Profil pro
    A la retraite...
    Inscrit en
    Janvier 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : A la retraite...
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2012
    Messages : 49
    Par défaut Modification d'un firmware (je pense en C++) pour une radio commande
    Bonjour à tous,

    Un autre sujet qui m'intéresse. Je dois avant tout dire que je suis pas du tout spécialiste en C ou C++. Je ne suis qu'un modeste bidouilleur et je ne fais que du copier/coller tout en essayant quand même de comprendre le code que je recopie.

    Il y a déjà plusieurs années (~ 20 ans) j'ai modifié ma radio commande en 2.4Ghz avec des modules Xbee pour la transmission et un Attiny2313 pour l'interface avec les servos.
    Dernièrement j'ai voulu remettre en route ma radio et le récepteur et module d'émission Xbee à pété. Donc je dois remplacer les deux...

    J'ai fouillé le net pour essayer d'en trouver. Y en a, mais à des prix exorbitants. (+ de 35€). J'ai trouvé des modules nRF24 à des prix vraiment intéressants (- de 5€). Y a pas photos...

    Maintenant, je dois modifier le firmware... voici le code qui fonctionne avec le Xbee que j'aimerais adapté au nRF24.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
     
    /******************************************************************************
     *   Program:           TX For O24RCP                                                                                                                                                 *
     *   Created:           2009                                                                                                                                    *
     *   Author:            C Courche et H Goncalves                                                                                                                        *
     *   Version:     V2.2                                                        *            
     ******************************************************************************/
     
     /* IMPORTANT : Cette création est mise à disposition selon le Contrat 
     *  Paternité-Pas d'Utilisation Commerciale-Partage des Conditions Initiales 
     *  à l'Identique 2.0 France disponible en ligne 
     *  http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ 
     *  ou par courrier postal à
     *  Creative Commons, 171 Second Street
     *  Suite 300, San Francisco, California 94105, USA.
     * / 
     
    	/*ATTENTION: l'auteur ne pourrait assumer la responsabilité
    	concernant toute modification ou utilisation inappropriée
    	de ce programme */
     
    #include <avr/io.h>
    #include <stdio.h>
    #include <string.h>
    #include <avr/interrupt.h>
    #include <avr/eeprom.h>
    #include <util/delay.h>
    #include <avr/wdt.h>
    #include <avr/pgmspace.h>
     
    // préselections de tempos de chien de garde:
    #define WDTCSR_16MS (1<<WDIE)	|	(0<<WDP3)	| 	(0<<WDP2) 	| 	(0<<WDP1) 	| 	(0<<WDP0)
    #define WDTCSR_32MS (1<<WDIE)	|	(0<<WDP3)	| 	(0<<WDP2) 	| 	(0<<WDP1) 	| 	(1<<WDP0)
    #define WDTCSR_64MS (1<<WDIE)	|	(0<<WDP3)	| 	(0<<WDP2) 	| 	(1<<WDP1) 	| 	(0<<WDP0)
    #define WDTCSR_1S  	(1<<WDIE)	|	(0<<WDP3)	|	(1<<WDP2) 	| 	(1<<WDP1) 	| 	(0<<WDP0)
    #define WDTCSR_2S  	(1<<WDIE)	|	(0<<WDP3)	|	(1<<WDP2) 	| 	(1<<WDP1) 	| 	(0<<WDP0)
    #define WDTCSR_4S  	(1<<WDIE) 	|	(1<<WDP3)	| 	(0<<WDP2) 	| 	(0<<WDP1) 	| 	(0<<WDP0)
     
    #define EEPROM_SECTION  __attribute__ ((section (".eeprom")))
     
    #define SYSCLK	8000000		//Fréquence du Quartz en Hz
     
    #define BAUD_RATE 19200		//vitesse standard RS232
     
    // plages des canaux 2.4GHz disponibles
    #define CanalMaxiInDoor 	0x1A	// canal maxi indoor
    #define CanalMaxiOutDoor 	0x17	// canal maxi outdoor
    #define CanalMiniInOutDoor 	0x0C	// canal mini indoor/outdoor
     
    // entrées/sorties TinY
    #define CavalierInDoor 	 1		// PortB1: cavalier Indoor(absent)/outdoor(présent)
    #define InterFailSafe  	 0    	// PortB0: BP Programmation failsafe
    #define LedTiny 		 4		// portB4: Led rouge du TinY
    #define Aux1             2     	// PortB2: voie auxiliaire PPM+1
     
    // paramétres encodage trame XBEE
    #define TypeTrameRs      		3	// Port B3: strap  selection type de trame série (FMS/HD)
    #define TesteFailSafe    		6	// Port B6: pin9/HE10 AVRISP(MISO); sert de test Failsafe(actif à 0) 
    #define TempoFailSafeMax 		2	// code progfail max (0=64µs; 1=1s; 2=4s)
    #define ResolutionTrameRs_FMS 	0	// mode d'encodage FMS
    #define ResolutionTrameRs_HD 	1	// mode d'encodage FMS
     
    // registres de l'UART 
    #define USR UCSRA
    #define UCR UCSRB	
    #define UBRR UBRRL	
    #define EICR EICRB
     
    // parametres debit RS232
    volatile char Id_Baud_Test; 						//contient le débit en test avec l'XBEE
    const char PROGMEM ListeBaud [] = {51,25,12,8}; 	//suivant le tableau 58 doc du Tiny2313
    //ou la version formule:
    //const char PROGMEM ListeBaud [] = {(SYSCLK/(9600 * 16L))-1,(SYSCLK/(19200 * 16L))- 1,(SYSCLK/(38400 * 16L))-1,8};
    #define ID_BAUD_RATE_MAX            3	// maxi 56K
    #define ID_WORKING_BAUD_RATE    	3   // débit  de travail...
     
    // table des temps de voies (utilisée aussi pour le scan des canaux)
    volatile unsigned int 	TempsVoies[15]={0,0,0,0,0,0,0,0,0,0,0,0};
     
    // mémoire de la séquence progammation XBEE
    const char PROGMEM SequenceInit_1 [] = "ATCE1,SP0,A25,DL0000FFFF,DH0,MY0,RN0,CH"; // XBEE en coordinator
    const char PROGMEM SequenceInit_2_In [] = ",PL0,WR,CN";		// émission à 10mW Indoor
    const char PROGMEM SequenceInit_2_Out [] = ",PL4,WR,CN";	// émission à 100mW Outdoor
    const char PROGMEM ATBD [] = "ATBD";
    const char PROGMEM VAL_ATBD[] = "D904";		// H,D904=55556 bauds précisement pour 56K 
    const char PROGMEM SeqProgXbee [] = "+++";
    const char PROGMEM WRCN [] = ",WR,CN";
    const char PROGMEM niv_dbm [] = "ATED4";	// demande au XBEE les niveaux -dBm de tous ses canaux
     
    // variables de travail
    volatile unsigned char 	Compteur;    				// nombre de trames répétées pour  programmation  Failsafe
    volatile unsigned char 	Indoor = 1,Canal;   		// variable permettant de selectionner le canal XBEE
    volatile unsigned char 	TempoFailSafe = 0;			// choix de la tempo de passage en failsafe (0; 1; 2)
    volatile unsigned char	Ok_Trame = 0;				// à 1: la trame est compléte et prête à envoyer
    volatile unsigned char 	VoieEnCours,VoiePrecedente;	// curseurs pour encodage de la trame
    volatile unsigned char 	Vmax;						// nombre de voies maxi de la trame PPM reçue en entrée
    volatile unsigned char 	Vsortie;					// nombre de voies à sortie (si ajout aux1)
    volatile unsigned char 	PasSynchro = 2; 			/*  2 : synchro vu 0 fois
    													    1 : synchro vu 1 fois
    													    0 : synchro vu 2 fois!!  => Nb Voies déterminé*/
     
    //déclaration des nouvelles fonctions
    void EnvoieTempsVoieRs (unsigned char NVoie, unsigned char TypeTrameSerie);
    void EnvoieFinTrame (unsigned char OrdreTrame, unsigned char TypeTrameSerie);
    void Rs232_Init (unsigned char IndexBaud);
    char uart_putchar (char c);
    void uart_putstr (char * str);
    void uart_putstr_P (const prog_char * str);
    unsigned char Wait_Ok( void );
    unsigned char Retourne_Char( void );
    void config_TX_XBEE(void);
     
     
    /****************************************************************************************************************
     
                              DEBUT DU PROGRAMME PRINCIPAL
     
    *****************************************************************************************************************/
    int main(void)
    {
    	volatile unsigned char i;				
    	volatile unsigned char ResolutionTrameRs;
     
        DDRB  = 0b10110000;                     // bit 0..3 et 6 (test fail) en entree
        PORTB = 0b01001111;                     // on tire les entrées au  1
     
        PORTB |= (1<<LedTiny);  				// Allume la LED 
     
    	config_TX_XBEE();	
     
    // configurations du Timer 1:
    	TIMSK |=  (1<<ICIE1);     			// Interruption Tmer1  sur Input Capture
     
    	TCCR1B |= (1<<ICES1);    							//Input capture sur front  montant
        TCCR1B |= (0<<CS12) | (1<<CS11) | (0<<CS10) ;    	// Clk/8 -> 1 tic = 1 µsec
     
        PORTB &= ~(1<<LedTiny);    		// on éteint la LED
     
    	sei();				// le module est OPERATIONNEL !	
     
     
     
    //***************************************** BOUCLE PRINCIPALE du MAIN *****************************************
     
        while(1)
    	{
    		if ( (!PasSynchro) && (Ok_Trame) )	// trame voies prête
    		{
    			ResolutionTrameRs = ResolutionTrameRs_FMS;
    			// on peut revenir en FMS en strappant à 0 le PortB,3; pas de strap -> mode HD (12bits)
     
    			if ( (PINB &(1<<TypeTrameRs)) ) ResolutionTrameRs = ResolutionTrameRs_HD;//par défaut HD!
     
    	// TESTE BP PROG FAILSAFE..................................
    			if (PINB &(1<<InterFailSafe))           
    			{						//BP PROG FAILSAFE relaché
    				Compteur = 0;   	
    				TempoFailSafe = 0;
    			}
     
    			else									
    			{						//BP PROG FAILSAFE appuyé
    				Compteur++;        
    			}
     
    	// ENVOI DE LA TRAME......................................	
    			for (i = 1;i < Vsortie+1;i++)
    			{
    				EnvoieTempsVoieRs (i, ResolutionTrameRs);
    			}
     
    	// ENVOI FIN TRAME........................................
    			if (Compteur == 100) // Maintenir le BP enfoncé durant 100 trame (soit environ 100x20ms=2sec)
    			{
    				EnvoieFinTrame (TempoFailSafe,ResolutionTrameRs); // alors seulement on ajoute l'octet de CMDE
    				Compteur = 0;
     
    				if (TempoFailSafe != TempoFailSafeMax) TempoFailSafe++; // si BP maintenu on passe la cmde à 01, puis 02
    			}
    			else 
     
    			{
    				EnvoieFinTrame (0xFF,ResolutionTrameRs ); // si pas de CMDE, on met "FF" à la place
    			}
     
    		Ok_Trame = 0; //la trame est partie, on raz pour attendre la suivante		  
    		} 
     
    	};   //boucle sans fin
     
    };
    //______________________________________________ fin PROGRAMME PRINCIPAL _________________________________________________
     
     
     
    //________________________________________________ DEBUT DES ROUTINES ____________________________________________________
     
    /*************************************************************************************************************************/
    //                                                Initialisation en émission du XBEE
    /*************************************************************************************************************************/
    void config_TX_XBEE(void)
    {
    	volatile unsigned char i,HFmaxi;		// ATTENTION: HFmaxi est la valeur absolue du niveau en -dBm!
    	volatile unsigned char Caractere,Chrono;
     
    	//------------------------------------- DETERMINATION  DU  CANAL (INDOOR/OUTDOOR) -----------------------------------   
        Indoor = 1;   	// force en Indoor par  défaut
     
    	if (  !( PINB & (1<<CavalierInDoor)) ) // si presence cavalier => OutDoor
    	{
    	    Indoor = 0;   
    	}
     
        Id_Baud_Test = ID_WORKING_BAUD_RATE; 	// teste à vitesse de travail
    	Rs232_Init (ID_WORKING_BAUD_RATE);		// initialisation UART
     
    	for(Chrono = 0;Chrono < 50;Chrono++) _delay_ms(10); //0.5sec pour init UART
     
    	cli();
    		wdt_reset();						// pas d'IT pendant cette action
    		WDTCSR = (1<<WDCE) | (1<<WDE);		// On démarre le Watchdog
    		WDTCSR = WDTCSR_2S;					// tempo WD à 2 sec
    	sei();
     
    	uart_putstr_P (SeqProgXbee); 			// 1er appel du XBEE
     
    	while (!Wait_Ok()); // il faut attendre le OK, sinon le WDTimer rebootera
     
    	// c'est bon on a le OK XBEE, on continue...
    	MCUSR &= ~(1<<WDRF);
    	WDTCSR |= (1<<WDCE) | (1<<WDE);	// Désactication du Watchdog
        WDTCSR = 0x00;
     
     	if (Id_Baud_Test != ID_WORKING_BAUD_RATE) 	// si vitesse XBEE pas la bonne...
     	{
         	uart_putstr_P (ATBD);		// ...envoi la vitesse de travail...
            uart_putstr_P (VAL_ATBD);
    	   	uart_putstr_P (WRCN);
    	   	uart_putchar (0x0D);		//CR 
     
         	while (!Wait_Ok());			// attend le OK
     
         	wdt_reset();
    		WDTCSR = (1<<WDCE) | (1<<WDE); 
    	    WDTCSR = (1<<WDE);		// provoque un Reset
     
    		while(1){}; 			// attend le reset pour tourner à la bonne vitesse
        }
     
    	// RECHERCHE  DU  CANAL LIBRE:
        uart_putstr_P (niv_dbm); 	//demande au XBEE ses niveaux -dBm pour chaque canal (en valeur absolue!)
    	uart_putchar (0x0D);  		//CR    
     
    	// RECEPTION DES 12 VALEURS DE PUISSANCE:
    	for (Caractere = 0;Caractere < 12; Caractere++)
    	{	
    		TempsVoies[Caractere] = Retourne_Char();	// la table tempsvoies sert a stocker les 12 niveaux -dBm
    	}
     
    	Caractere = 0;					//  index de scrutation des canaux, jusqu'à canal (limite Indoor/outdoor)
     
        Canal = 9;						// 	9 canaux possibles en Outdoor  (100mW)
     
        if (Indoor) 	Canal = 12;		// 	12 canaux possibles en Indoor  (10mW)
     
    	HFmaxi = 0;	                	//	maximum en valeur absolue: à ce niveau le canal n'est pas disponiblr
     
    	for (i = 0;i < Canal; i++)
    	{
    		if (TempsVoies[i] > HFmaxi)		// scrute toutes les valeurs de la table...
    		{
    			HFmaxi = TempsVoies[i];		//...pour garder la plus élevée
    			Caractere = i;				// garde la position dans la table du meilleur canal retenu
    		}
    	}
     
    	if (Caractere == Canal)			// -0db partout, canaux saturés!
    	{
     
    		while (1) 					// clignote le led en boucle: y a pas de place pour cette fois!
    		{
    		    for(Caractere = 0;Caractere < 100;Caractere++) _delay_ms(10);
    		    PORTB &= ~(1<<LedTiny);                                     // Eteint la LED		    
    		   	for(Caractere = 0;Caractere < 100;Caractere++) _delay_ms(10);
    		   	PORTB |= (1<<LedTiny);                                      // Allume la LED
    		}
     
    	}
     
    	// on a notre canal! on continue...	
        Canal = CanalMiniInOutDoor + Caractere;   		// recalcule le N°CANAL choisi parmis les 9 ou 12
     
    	// ENVOI  DE LA SEQUENCE AU  XBEE:	
    	uart_putstr_P(SequenceInit_1);					// 1er tronçon...
     
    	Caractere = (Canal>>4); 						// ...puis le Canal  utilisé: 1er caractère (poids fort):	
    		if (Caractere > 9)	Caractere += 7; 		// 								passage en Hexa...
    		uart_putchar (Caractere + 48);    			// ...puis le caractère en ASCII!
     
    	Caractere = (Canal & 0b00001111); 				// ensuite 2nd caractère (poids faible):
    		if (Caractere > 9)	Caractere += 7; 		// 								passage en Hexa...
    		uart_putchar (Caractere + 48);    			// ...puis le caractére en ASCII!	
     
    	if (Indoor) uart_putstr_P(SequenceInit_2_In);	// et  enfin 2ème troncon...
    	else 	uart_putstr_P(SequenceInit_2_Out);		// ...en fonction du strap Indoor/Outdoor
     
    	uart_putchar (0x0D);   // important:le RETOUR  CHARIOT!!!!	
     
    };
     
     
    /*************************************************************************************************************************/
    //                                                Initialisation RS232
    /*************************************************************************************************************************/
    void Rs232_Init (unsigned char IndexBaud)
    {	
    	UCSRB = (1 << TXEN) | (1 << RXEN);  		// autorisation  Tx et Rx mais sans interruption
    	UBRRL = (pgm_read_byte(&ListeBaud[IndexBaud]));
    };
     
     
    /*************************************************************************************************************************/
    //                                       Envoi d'un caractere de SRAM vers UART
    /*************************************************************************************************************************/
    char uart_putchar (char c)
    {
    	loop_until_bit_is_set(USR, UDRE);	//attente buffer UART vide pour envoyer le caractère
    	UDR = c;
    	return (0);
    };
     
     
    /*************************************************************************************************************************/
    //                                        Envoi d'un string de SRAM vers UART
    /*************************************************************************************************************************/
    void uart_putstr (char * str)
    {
    	while (str[0] != 0)					// tant qu'il reste un caractère de la chaine...
    	{
    	    uart_putchar (str[0]);			// ...on l'envoie!
    	    str++;
    	}
    };
     
     
    /*************************************************************************************************************************/
    //                                      Envoi d'un string de Mémoire (FLASH) vers UART
    /*************************************************************************************************************************/
    void uart_putstr_P (const prog_char * str)
    {
    	while (pgm_read_byte(str) != 0)				// tant qu'il reste un caractère de la chaine stockée en mémoire...
    	{
    	    uart_putchar (pgm_read_byte(str));		// ...on l'envoie!
            str++;
    	}
    };
     
     
    /*************************************************************************************************************************/
    //                                                Attente OK + CR du XBBE
    /*************************************************************************************************************************/
    unsigned char Wait_Ok( void )
    {
    	unsigned char  Recu;
     
    	while ( !(UCSRA & (1<<RXC)) );		
    	Recu = UDR;
    	if (Recu != 'O') return 0;			// attente "O"
     
    	while ( !(UCSRA & (1<<RXC)) );		
    	Recu = UDR;
    	if (Recu != 'K') return 0;			// attente "K"
     
    	while ( !(UCSRA & (1<<RXC)) );		// attente CR
    	Recu = UDR;							
    	if (Recu != 0x0D) return 0;			// vérification
     
    	return 1; //Ok  on revient
    };
     
     
    /**************************************************************************************************************************/
    // 									Attente 2 caractéres + CR (réponses du XBEE)
    /**************************************************************************************************************************/
    unsigned char Retourne_Char( void )
    {
    	// on reçoit une valeur Hexadécimale, codée sur 2 car. ASCII, on la retourne en Hexa sur 1 octet
    	unsigned char  Recu,Blanc;
     
    	while ( !(UCSRA & (1<<RXC)) );		// attente caractère arrivé dans l'UART
    	Blanc = UDR;
    	if (Blanc > 64) Blanc -= 7;			// premier caractère ASCII...
    	Recu = (Blanc - 48)<<4;				// pour le poids fort....
     
    	while ( !(UCSRA & (1<<RXC)) );		
    	Blanc = UDR;						
    	if (Blanc > 64) Blanc -= 7;			// second caractère ASCII...
    	Recu = Recu + (Blanc - 48);			// .... pour finir en Hexa (poids fort + poids faible)
     
        while ( !(UCSRA & (1<<RXC)) ); 	// ON attend CR
    	Blanc = UDR;  						// il suffit de le lire pour continuer
     
    	return Recu; 	//Ok  on raméne la valeur reçue en ASCII
    };
     
     
    /**************************************************************************************************************************/
    //                                              envoie  des temps de voie
    /**************************************************************************************************************************/
    void EnvoieTempsVoieRs (unsigned char NVoie, unsigned char TypeTrameSerie)
    {
    	if  ( ! (PINB & (1<<TesteFailSafe))) return;
     
    	switch (TypeTrameSerie)
    	{
    		case ResolutionTrameRs_FMS:						// cas FMS
     
     
            	if ( TempsVoies[NVoie]< 760) {uart_putchar(0); break;}			
    			if ( TempsVoies[NVoie]> 2290){ uart_putchar(0xFE); break;}			
     
    		    uart_putchar ( (char) (((TempsVoies[NVoie])-760)/6) );		// encodage norme FMS
    		break;
     
     
    		case ResolutionTrameRs_HD :						// cas HD
     
    			// poids faible  d'abord
    			if ((char) (TempsVoies[NVoie]) == 0xFF)uart_putchar(0xFE);		
     
    			else 	uart_putchar ( (char) (TempsVoies[NVoie]) );			// encodage 12 bits...
     
    			// Poids Forts ensuite
                uart_putchar ( (char)( (TempsVoies[NVoie]) /256) );			// ...sur 2 octets
    		break;
     
    	}
     
    };
     
     
    /**************************************************************************************************************************/
    //                                                envoie  fin de trame
    /**************************************************************************************************************************/
    void EnvoieFinTrame (unsigned char OrdreTrame, unsigned char TypeTrameSerie)
    {
        if  ( ! (PINB & (1<<TesteFailSafe))) return;
    	switch (TypeTrameSerie)
    	{
    		case ResolutionTrameRs_FMS:		// cas FMS
     
                uart_putchar(0xFF);			
    			if ( OrdreTrame != 0xFF)
    			{
                	uart_putchar(0xFF);		// 2 FF suivi de l'octet de cmde
                	uart_putchar(OrdreTrame);
    			}
    		break;
     
    		case ResolutionTrameRs_HD:		// cas HD
     
            	uart_putchar(0xFF);
            	uart_putchar(OrdreTrame);	// 1 FF suivi de l'octet de cmde (00, 01, 02, FF)
    		break;
    	} 
     
    };
     
    //__________________________________________________ fin DES ROUTINES ______________________________________________________
     
     
     
     
    //_________________________________________ DEBUT TRAITEMENT DES INTERRUPTIONS ___________________________________________
     
     
    //******************************************* INTERRUPTION SUR FRONT DE PULSE ********************************************
    //				ici voieEnCours représente le numéro  de la voie qui vient de finir à l'interruption
     
    SIGNAL(SIG_INPUT_CAPTURE1) 
    {	
    	volatile unsigned int TempsMesure;
     
    	TCNT1H = 0;        // reset TCNT1
    	TCNT1L = 4;        // reset TCNT1 :4! pourquoi pas 0 ??? ... +4µs (<0,1°) c'est pas bien grave...
     
    	TempsMesure = ICR1L;
    	TempsMesure += (ICR1H*256);		// On récupère le temps de la voie qui vient de finir
     
     
    	//------------------------------ COMPTAGE DU NOMBRE DE VOIES ENTRE 2 SYNCHROS --------------------------------------
     
    	if (PasSynchro)	// cherche le temps de synchro (2 fois) pour scruter ce qui vient entre les deux
    	{
    		if (TempsMesure > 6000)  // plus de 6ms ==> c'est le temps de synchro
    		{
    			switch (PasSynchro)
    			{			
    				case 2	: 				// à 2: ==> première fois passage du temps de synchro
    				VoieEnCours = 1;		// initialise le compteur de voies à 1
    				break;
     
    				case 1 : 				// à 1: ==> deuxième passage du synchro (on a compté les pulses entre les 2)
    				Vmax = VoieEnCours - 1;	// on calcule le nombre maxi de voies trouvées en entrée PPM
    				VoieEnCours = 1;		// On se recale au début de table
    				break;				
    			}	
    			PasSynchro--; 		// décrémente le nombre de passage synchro
    			return;		
    		} 		
    		VoieEnCours++; 		// incrémente le compteur de voies à chaque pulses (vue entre les 2)
    		return;	
    	}
     
    	//--------------------------- ENREGISTREMENT DES TEMPS DE VOIES POUR CONSTRUIRE LA TRAME XBEE ---------------------
     
    	TempsVoies[VoieEnCours] = TempsMesure;	// enregistre le temps de voie dans la table
    	VoiePrecedente = VoieEnCours;	
    	VoieEnCours++;							// passe à la voie suivante
     
    	if ( VoieEnCours == (Vmax+1))	//on est à la fin de la dernière voie PPM entrée
    	{
    		Vsortie = Vmax;			// nombre de voies à sortir
    		VoieEnCours = 0;  		// réinitialise la table à la première voie
            Ok_Trame = 1; 			// on autorise l'envoi de la trame
     
    		// ajoute voie AUX1: facultatif ------		
    		if (Vmax < 9)   // fait seulement si on n'a que 8 voies maxi en entrée
    		{
            	Vsortie = Vsortie + 1;	// ajoute 1 voie dans la trame de sortie
     
    			if (PINB &(1<<Aux1))    // teste la Touche auxiliaire
    			{
    				TempsVoies[Vmax+1] = 1000;  // 1ms si strap ouvert
    	        }
     
    	        else
    	        {
    				TempsVoies[Vmax+1] = 2000;	// 2ms si strap fermé
    	        }
    	    }
    		//------------------------------------			
    	}
     
    	// ---------------------------------- CAS d'INCOHERENCES DU TEMPS MESURE -------------------------------------------
    	/*                 ici VoieEnCours représente la voie que l'on est en train de parcourir	
                        par contre TempsMesure est le temps de la voie précédente
    			        si ce TempsMesure est hors norme, on va refaire une passe de Passynchro
    			        ...çà sert à se resynchronise au moment d'une commutation de l'inter MAITRE/ELEVE en écolage      */
     
       if (VoiePrecedente == 0) // seulement si on n'a pas commencer à encoder la trame: sinon =1 au mini
       {
    		if ( (TempsMesure < 4000) || (TempsMesure > 20000)) 	// entre 4ms et 20ms c'est un temps de synchro PPM
            {
              	PasSynchro = 2; 									//on a perdu le fil on refait une passe de synchro
              	return;
            }
       }
     
       else    // n'importe qu'elle autre numéro de voie autre que synchro (0)
       {
             // si le temps de voie n'est pas aux normes on se mets en condition de synchro
            if (  (TempsMesure < 700) || (TempsMesure > 3000)) 	// si une voie est faussée...
            {
              	PasSynchro = 2;	 									// ...on refait une passe de synchro
              	return;
            }
     
       }
     
    	PORTB &= ~(1<<LedTiny); //LED éteint
    };
     
    //_________________________________________________ fin IT FRONT DE PULSE _________________________________________________
     
     
     
    /*************************************************************************************************************************/
    //                                                 interruption sur watchdog
    /*************************************************************************************************************************/
    SIGNAL(WDT_OVERFLOW_vect)
    {
     
        WDTCSR = WDTCSR_2S;			// relance le WDT à 2 sec
        if (Id_Baud_Test >= ID_BAUD_RATE_MAX )Id_Baud_Test = 0; // passe à la vitesse suivante
    		else Id_Baud_Test++;
    	Rs232_Init (Id_Baud_Test);
    	uart_putstr("+++");    
    };
     
    //_______________________________________________ FIN DES INTERRUPTIONS __________________________________________________

  2. #2
    Membre averti
    Homme Profil pro
    A la retraite...
    Inscrit en
    Janvier 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : A la retraite...
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2012
    Messages : 49
    Par défaut
    Bonjour à tous,

    J'ai trouvé un code pour Arduino qui utilise un nRF24. Je l'ai testé sur une Leonardo et ça fonctionne. Ce que j'aimerais avoir c'est quelques bricoles supplémentaires que l'on a dans le firmware original . Par exemple: une recherche de canaux disponibles, une shynchronisation avec le récepteur, un indicateur d'état, led fixe et clignotante quand l'emetteur a trouvé un canal disponible.

    C'est pas simple pour moi, et je cherche de l'aide...

    Merci

    Voilà le code Arduino

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <MsTimer2.h>  // Bibliothèque pour gérer les timers
     
    #define CE_PIN 9
    #define CSN_PIN 10
     
    RF24 radio(CE_PIN, CSN_PIN);
     
    const byte address[6] = "00001";
    const int channels[] = {2, 76, 43, 98, 55};  // Séquence de canaux FHSS
    const int numChannels = sizeof(channels) / sizeof(channels[0]);
    volatile int currentChannel = 0;
     
    const int ppmPin = 2;  // Pin où le signal PPM est connecté
    volatile unsigned long lastPPMTime = 0;
    volatile unsigned long ppmFrame[8] = {0};
     
    void changeChannel() {
      currentChannel = (currentChannel + 1) % numChannels;  // Passer au canal suivant
      radio.setChannel(channels[currentChannel]);  // Sélectionner le nouveau canal
    }
     
    void readPPM() {
      unsigned long time = micros();
      static int channelIndex = 0;
      unsigned long duration = time - lastPPMTime;
      lastPPMTime = time;
     
      if (duration > 3000) {  // Détection du début du frame
        channelIndex = 0;
      } else {
        if (channelIndex < 8) {
          ppmFrame[channelIndex] = duration;
          channelIndex++;
        }
      }
    }
     
    void setup() {
      Serial.begin(9600);
      radio.begin();
      radio.openWritingPipe(address);  // Ouvrir le pipe 0 pour écrire
      radio.setPALevel(RF24_PA_LOW);   // Niveau de puissance
      radio.stopListening();           // Arrêter d'écouter
      radio.setChannel(channels[currentChannel]);  // Sélectionner le canal initial
     
      MsTimer2::set(100, changeChannel);  // Appeler changeChannel toutes les 100 ms
      MsTimer2::start();                  // Démarrer le timer
     
      attachInterrupt(digitalPinToInterrupt(ppmPin), readPPM, RISING);  // Configurer l'interruption pour lire le signal PPM
    }
     
    void loop() {
      radio.write(&ppmFrame, sizeof(ppmFrame));  // Envoyer les données PPM
      delay(90);  // Attendre avant d'envoyer le 
    }

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 464
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 464
    Par défaut
    Bonjour,
    Après examen rapide du code présenté ici, je ne vois rien qui concerne le C++. Il semble qu'il s'agisse purement de langage C, ce qui est habituel avec les pilotes de matériel et les ressource de bas niveau.

    Je déplace ton message dans le forum C.

  4. #4
    Membre averti
    Homme Profil pro
    A la retraite...
    Inscrit en
    Janvier 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : A la retraite...
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2012
    Messages : 49
    Par défaut
    Ok, merci...

  5. #5
    Membre averti
    Homme Profil pro
    A la retraite...
    Inscrit en
    Janvier 2012
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : A la retraite...
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2012
    Messages : 49
    Par défaut
    J'ai ajouté une modification au firmware Arduino. La led intégrée à la Leonardo cligote sur timer.
    Mais je garde la solution qu'elle clignote uniquement lorsque l'association avec le récepteur sera active.
    Je fouille toujours...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
     
    #include <PPMReader.h>
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
     
    volatile bool toggleState = false;
     
    // Définition des broches pour le module nRF24
    RF24 radio(9, 10); // CE, CSN
     
    // Adresse des pipes
    const byte address[6] = "00001";
    const int channels[] = {2, 76, 43, 98, 55};  // Séquence de canaux FHSS
    const int numChannels = sizeof(channels) / sizeof(channels[0]);
    int currentChannel = 0;
     
    // Tableau pour stocker les valeurs des canaux PPM
    int ppmChannels[8];
     
    const int pinPPMIn = 2;
    const int pinPPMOut = 4;
    //const int numChannels = 8;
    PPMReader ppm(pinPPMIn, numChannels);
     
    void setup() {
     
    // Configure la LED intégrée comme sortie
      pinMode(LED_BUILTIN, OUTPUT);
     
    // Configure Timer1
      noInterrupts();           // Désactiver les interruptions globales pendant la configuration
      TCCR1A = 0;               // Mettre le registre TCCR1A à 0
      TCCR1B = 0;               // Mettre le registre TCCR1B à 0
      TCNT1  = 0;               // Initialiser le compteur à 0
     
      // Configure le timer pour une fréquence de 1 Hz (1 seconde)
      // 16 MHz (clock) / 1024 (prescaler) = 15625 ticks per second
      // 15625 ticks per second / 1 Hz = 15625 ticks per interrupt
      OCR1A = 7812;            // Comparer la valeur du registre
      TCCR1B |= (1 << WGM12);   // Mode CTC (Clear Timer on Compare Match)
      TCCR1B |= (1 << CS12) | (1 << CS10); // Prescaler 1024
      TIMSK1 |= (1 << OCIE1A);  // Activer l'interruption par comparaison
     
      interrupts();             // Activer les interruptions globales
     
    // Initialisation du module nRF24
      Serial.begin(9600);
      radio.begin();
      radio.openWritingPipe(address);
      radio.setPALevel(RF24_PA_MAX);
      radio.stopListening();
     
      pinMode(pinPPMOut, OUTPUT);
      digitalWrite(pinPPMOut, LOW);
     }
     
    void loop() {
     
    radio.setChannel(channels[currentChannel]);  // Sélectionner le canal actuel
     
    if (radio.available()) {
        /*
        char text[32] = {0};
        radio.read(&text, sizeof(text));
        Serial.println(text);
        */
      }
     
      currentChannel = (currentChannel + 1) % numChannels;  // Passer au canal suivant
      delay(50);  // Attendre un peu avant de sauter au prochain canal
     
      const int syncLength = 4000; // longueur de l'intervalle de synchronisation en microsecondes
      const int pulseLength = 300; // longueur des impulsions en microsecondes
     
    // Envoi des valeurs des canaux PPM par nRF24
      radio.write(&ppmChannels, sizeof(ppmChannels));
     
      // Générer le signal PPM sur la broche 4
      digitalWrite(pinPPMOut, HIGH);
      delayMicroseconds(syncLength);
      digitalWrite(pinPPMOut, LOW);
      delayMicroseconds(pulseLength);
     
      for (int i = 0; i < numChannels; i++) {
        int value = ppm.latestValidChannelValue(i + 1, 0);
        digitalWrite(pinPPMOut, HIGH);
        delayMicroseconds(value);
        digitalWrite(pinPPMOut, LOW);
        delayMicroseconds(pulseLength);
      }
    /*
      // Afficher les valeurs des canaux sur le moniteur série
      
      for (int i = 0; i < numChannels; i++) {
        int value = ppm.latestValidChannelValue(i + 1, 0);
        //Serial.print("Affichage\n\r");
        Serial.print("Channel ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.print(value);
        Serial.print("us");
        Serial.print("\t");
      }
      //Serial.println();
      Serial.print("\r");
      delay(100);
      */
    }
     
    ISR(TIMER1_COMPA_vect) {
      // Inverser l'état de la LED intégrée
      toggleState = !toggleState;
      if (toggleState) {
        PORTB |= (1 << PORTB0);  // Allume la LED intégrée (PB0)
      } else {
        PORTB &= ~(1 << PORTB0); // Éteint la LED intégrée (PB0)
      }
    }

Discussions similaires

  1. Débuté (Aide pour une modif de serveur)
    Par mimagyc dans le forum C++
    Réponses: 8
    Dernier message: 20/12/2006, 23h19
  2. modification de taille de zone à l'intérieur d'une fenetre
    Par pinot dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 19/09/2006, 00h07
  3. Réponses: 3
    Dernier message: 11/06/2006, 02h34
  4. modification de données pour une ligne
    Par Skizo dans le forum Access
    Réponses: 5
    Dernier message: 12/05/2006, 11h05
  5. Besoin d'aide pour une requête de MAJ (modif. de car.)
    Par ptitscrat dans le forum Access
    Réponses: 5
    Dernier message: 22/03/2006, 17h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo