Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

funzione rand() su scheda STK500 (ATMEL)

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentemassimonanni86 » 17 mar 2012, 14:18

Salve a tutti, sono fresco fresco d' iscrizione.

Ho un dubbio da porvi:
sto programmando, con un Programmatore ATMEL (l' STK500), un micro (ATMEGA8515L, quello base che si trova nel kit) con l'intendo di avere dei "delay", cioè dei momenti in cui il micro non esegue operazioni, di tempo randomico.
Uso come Compilatore l' "AVR-Studio 4" che, scritto il codice con relative librerie ".h" inserite per il "delay_ms" e il "rand", non da problemi di Debug (0 errori, 0 warning).
Una volta flashata la memoria del micro (con la EEPROM è uguale), è come se questo non riuscisse ad eseguire l'operazione ed in un ciclo "while(1)" che racchiude tutto il codice, tutte le operazioni dopo l'istruzione "int a=rand();" per esempio, non vengono eseguite.

ESEMPIO DEL CODICE:
********************************************************************************************
#include <avr/io.h>

#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h> //libreria per il "delay"
#include <util/delay_basic.h>
#include <stdlib.h> //libreria per il "rand"

#define DirectionPortLED DDRC
#define LED_ON PORTC
#define msec 100


void InitializeLED()
{
DirectionPortLED = 0xFF;
LED_ON = 0xFF;
}


int main(void)
{
int tot;
double tot_1;

InitializeLED();

while(1){
PORTC = 0b11111111; //spengo tutti i LED
_delay_ms(msec);

PORTC = 0b11111110; //accendo il primo LED
_delay_ms (msec);

tot=rand()%100; //così prendo num tra 0 e 99.
tot_1=(double)tot; //delay vuole in ingresso un double

PORTC = 0b11111101; //accendo il secondo LED
_delay_ms (tot_1);
}
}
********************************************************************************************

Quindi le operazioni dopo il rand() non vengono eseguite, MA iterativamente, le prime (spegnere tutti i led ed accendere il primo) si.

NON CAPISCO--> AIUTO!
Avatar utente
Foto Utentemassimonanni86
0 3
 
Messaggi: 5
Iscritto il: 17 mar 2012, 13:55

1
voti

[2] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentegiacky98 » 17 mar 2012, 23:35

Io sto usando un'Atmega16 (molto simile al tuo micro) e con questo codice (modificato partendo dal tuo) non ho nessun problema:
Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
*  Author: Giacky98
*/

#include <avr/io.h>

#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h> //libreria per il "delay"
#include <stdlib.h> //libreria per il "rand"

#define LEDDDR      DDRC
#define LEDPORT   PORTC
#define msec      100


void Init(void)
{
   LEDDDR = 0xFF; // Imposto la porta C come uscita
   LEDPORT = 0xFF; // Spengo tutti i LED
}


int main(void)
{
   int d; // La variabile che conterrà il numero casuale
   
   Init(); // Inizializzo la porta del LED come uscita

   while(1){
      LEDPORT = ~0x00; // Spengo il primo LED
      _delay_ms(msec); // Delay
      
      LEDPORT = ~0x01; // Accendo il primo LED
      _delay_ms(msec); // Delay
      
      d = (int)(rand()%100); // Ottengo un valore casuale da 0 a 99
      
      LEDPORT = ~0x02; // Accendo il secondo LED
      _delay_ms(d); // Delay (tempo casuale)
   }
   
   return 0; // Non serve a niente ma bisogna metterlo
}

Il codice puoi usarlo direttamente sul tuo micro senza modificare niente.

Come vedi, ho semplificato il codice, ho usato le notazioni esadecimali per assegnare i valori alle porte e ho sistemato le linee per ottenere il numero casuale con una semplice istruzione:
Codice: Seleziona tutto
d = (int)(rand()%100);

Solo una domanda, nel tuo codice, per accendere il LED, imposti il bit a 0. Sei sicuro che per il tuo circuito sia corretto? Considerando che in questo caso penso non abbia molta importanza, ma se usi un circuito come questo:

ottieni l'accensione "inversa", cioè quando tu nei commenti scrivi che accendi, in realtà spegni, e viceversa.

La cosa è diversa, invece, se usi questo circuito:

allora i commenti sono corretti.

Spero di esserti stato d'aiuto :-)
Avatar utente
Foto Utentegiacky98
10 1 4
New entry
New entry
 
Messaggi: 70
Iscritto il: 6 dic 2011, 14:57

0
voti

[3] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentemassimonanni86 » 19 mar 2012, 16:35

Ti ringrazio innanzi tutto per la chiarezza e meticolosità con il quale mi hai risposto.

Venendo al dunque: ho provato a copiare il codice direttamente come tu mi hai riportato, ma quello che accade è che il 1° LED si accende con il suo delay (dato da #DEFINE), ma il secondo no.

Per tagliare la testa al toro ho scritto l'istruzione "d=(int)(rand()%100)" all'inizio del ciclo while(1) e, dopo la programmazione del micro con tal codice, ho tristemente visto che, COME SCRITTO SUL PRIMO messaggio POSTO SUL FORUM, sembra quasi che tale micro non sia in grado di fare la funzione "rand()".

Pensi sia cosa plausibile?
Mi informerò un po' in rete comunque.

Grazie mille delle informazioni.

Massimo
Avatar utente
Foto Utentemassimonanni86
0 3
 
Messaggi: 5
Iscritto il: 17 mar 2012, 13:55

0
voti

[4] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentegiacky98 » 19 mar 2012, 16:49

Ho velocemente cercato in rete se qualcuno ha avuto qualche problema relativo all'uso di rand() sul tuo Atmega, ma non ho trovato niente.

Quindi i casi sono 2:
o il micro è danneggiato, dal punto di vista hardware;
o c'è qualche errore nel software.

Nel primo caso, l'unico modo è sostituire il micro.
Nel secondo, ci sono principalmente due fattori che possono causare il problema: potrebbe essere un errore di codice (che magari sul mio Atmega16 funziona ma sul tuo no anche se non capisco perché) oppure un problema di compilazione.
Riguardo a quest'ultimo, volevo sapere, stai usando le ottimizzazioni del codice? Se sì, a che livello?
Avatar utente
Foto Utentegiacky98
10 1 4
New entry
New entry
 
Messaggi: 70
Iscritto il: 6 dic 2011, 14:57

0
voti

[5] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentemassimonanni86 » 19 mar 2012, 16:53

No, non so nemmeno cosa tu intenda per "ottimizzazione del codice".. magari risulterò un po' un novello, ma non si finisce mai di imparare! :) :) :)
Avatar utente
Foto Utentemassimonanni86
0 3
 
Messaggi: 5
Iscritto il: 17 mar 2012, 13:55

0
voti

[6] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentegiacky98 » 19 mar 2012, 17:05

Non preoccuparti, fino a un mese fa non sapevo neanch'io cos'era :D

Adesso non ti so dare una definizione perfetta, ma ti posso brevemente dire che l'ottimizzazione è un'operazione che compie il compilatore (avr-gcc) prima di effettuare la compilazione vera e propria. L'ottimizzazione consiste nel ridurre parti di codice in cui ci sono istruzioni in eccesso o rimuovere automaticamente variabili non necessarie, per esempio.
Oltre ad essere utile per ridurre la dimensione del programma, è anche utile per far funzionare meglio certe procedure. Per esempio, la libreria <util/delay.h> produce un Warning se l'ottimizzazione non è abilitata.

Per selezionare il livello di ottimizzazione (-O1, -O2, ...), da AVR Studio fai click destro sul progetto (nella finestra di esplorazione a destra) e fai "Properties". Si aprono le proprietà del progetto. Da qui mi sembra devi andare sulla scheda Toolchain e trovare la voce Compiler Optimization o Code Optimization. Da qui puoi impostare il livello.

Probabilmente adesso le ottimizzazioni saranno disabilitate, prova a mettere un'ottimizzazione di secondo livello (-O2), compilare e caricare il codice.
Avatar utente
Foto Utentegiacky98
10 1 4
New entry
New entry
 
Messaggi: 70
Iscritto il: 6 dic 2011, 14:57

0
voti

[7] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentemassimonanni86 » 19 mar 2012, 17:23

:( :( :(

Nemmeno con il terzo livello di ottimizzazione il risultato è lo stesso!

Dai, ti ringrazio ugualmente per il tuo aiuto!
Proverò ad acquistare un altro micro, magari prima di essermi informato da qualche ex docente dell'università!
Avatar utente
Foto Utentemassimonanni86
0 3
 
Messaggi: 5
Iscritto il: 17 mar 2012, 13:55

0
voti

[8] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentegiacky98 » 19 mar 2012, 19:03

Molto strano, perché a me funziona anche con ottimizzazione pari a 0...

Comunque, c'è un altro modo per ottenere numeri casuali. Ci sono tanti altri modi, basta cercare su Google.
Per esempio si possono usare alcuni algoritmi per ottenere il numero. Ne ho provati un paio di semplici, ma ho scoperto che il risultato non è molto "casuale", perché alla fine i numeri sono sempre gli stessi 20-30 che si ripetono...

Ho però trovato un modo per ottenere un numero abbastanza casuale: usare il timer.
Con questo codice funziona abbastanza bene (dal punto di vista della casualità):
Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
*  Author: Giacky98
*/

#define F_CPU 1000000UL // 1 MHz

#include <avr/io.h>
#include <util/delay.h> //libreria per il "delay"

#define LEDDDR      DDRC
#define LEDPORT      PORTC
#define msec      100

void Init(void)
{
   LEDDDR = 0xFF; // Imposto la porta C come uscita
   LEDPORT = 0xFF; // Spengo tutti i LED
   TCNT0=0; // Inizializza il contatore del timer
   TCCR0|=(1<<CS02)|(1<<CS00); // Prescaler = FCPU/1024
}

int main(void)
{
   int d; // La variabile che conterrà il numero casuale
   
   Init(); // Inizializzo la porta del LED come uscita
   
   while(1){
      LEDPORT = ~0x00; // Spengo il primo LED
      _delay_ms(msec); // Delay
      
      LEDPORT = ~0x01; // Accendo il primo LED
      _delay_ms(msec); // Delay
      
      d = TCNT0%100; // Ottengo il valore dal contatore del timer (0 - 99)
      
      LEDPORT = ~0x02; // Accendo il secondo LED
      _delay_ms(d); // Delay (tempo casuale)
   }
   
   return 0; // Non serve a niente ma bisogna metterlo
}


Non sono sicuro che funzioni sul tuo AVR senza bisogno di modifiche, prova e fammi sapere se dà errori :-)
Avatar utente
Foto Utentegiacky98
10 1 4
New entry
New entry
 
Messaggi: 70
Iscritto il: 6 dic 2011, 14:57

0
voti

[9] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentemassimonanni86 » 20 mar 2012, 1:07

Flebilmente il secondo LED si accendeva, ma provando a variare il codice (dao chè il tempo di accensione non mi sembrava così "random") in quello sotto per es.:

while(1){
d = TCNT0%100; // Ottengo il valore dal contatore del timer (0 - 99)

LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(d); // Delay

LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(d); // Delay

LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}

Ottengo che nessun LED si accende!
Anche provando ad aumentare il tempo randomico scelto ("%1000"), magari avessi problemi a vedere un flash del LED di 99 milli secondi. Ma nemmeno in tal modo funziona.

La cosa non me la so spiegare.

Grazie comunque del tuo supporto ed aiuto!
Avatar utente
Foto Utentemassimonanni86
0 3
 
Messaggi: 5
Iscritto il: 17 mar 2012, 13:55

0
voti

[10] Re: funzione rand() su scheda STK500 (ATMEL)

Messaggioda Foto Utentegiacky98 » 20 mar 2012, 21:17

E' veramente molto strano... Il codice come l'hai modificato a me funziona... :?

Allora, probabilmente non funziona benissimo sul tuo perché tra Atmega8515 e Atmega16 i timer sono un po' diversi.
Ora non ho avuto il tempo di cercare su internet i registri del timer del tuo micro, ma ti consiglio di leggere una guida o un tutorial (anche in inglese, penso non ci siano problemi) sui timer degli AVR, perché è importante conoscerli e saperli usare correttamente. Io ho imparato da questa http://extremeelectronics.co.in/avr-tutorials/avr-timers-an-introduction/.

Comunque, proviamo un altro modo, questa volta usiamo un'algoritmo. Prova questo codice:
Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
*  Author: Giacky98
*/

#define F_CPU 1000000UL // 1 MHz

#include <avr/io.h>
#include <util/delay.h>

#define LEDDDR      DDRC
#define LEDPORT      PORTC
#define msec      100

unsigned long x = 0;

/*****Seek changing function*********************/
void srand(unsigned long s) {
   x = s;
}

/*****random number function*********************/
int randm(void) {
   x = x * 1664525L + 1013904223L;
   return ((int)((x>> 17) & 0x7fff));
}

void Init(void)
{
   LEDDDR = 0xFF; // Imposto la porta C come uscita
   LEDPORT = 0xFF; // Spengo tutti i LED
}

int main(void)
{
   int d; // La variabile che conterrà il numero casuale
   
   Init(); // Inizializzo la porta del LED come uscita
   srand(0); //defining starting point of seek
   
   while(1){
      LEDPORT = ~0x00; // Spengo il primo LED
      _delay_ms(msec); // Delay
      
      LEDPORT = ~0x01; // Accendo il primo LED
      _delay_ms(msec); // Delay
      
      d = randm()%250+1; // Ottengo il valore casuale (1 - 250)
      
      LEDPORT = ~0x02; // Accendo il secondo LED
      _delay_ms(d); // Delay (tempo casuale)
   }
   
   return 0; // Non serve a niente ma bisogna metterlo
}


Fammi sapere se funziona. A me non dà problemi... se non funziona sinceramente non saprei proprio quale potrebbe essere il problema... :?
Avatar utente
Foto Utentegiacky98
10 1 4
New entry
New entry
 
Messaggi: 70
Iscritto il: 6 dic 2011, 14:57


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti