==premiers pasavec le tiny==
La première étape est de finir mon travail en retard sur le fabISP : comme j'attendais l'arrivée des composants, je n'ai pas eu le temps de programmer le circuit à temps. De plus je ne comprenais pas bien la logique d'alimentation du circuit : je croyais que le programmateur alimentait la puce cible alors qu'il fallait qu'elle le soit séparément...
il faut avoir téléchargé le compilateur [http://www.avr-asm-tutorial.net/gavrasm/index_en.html gavrasm]
Une fois décompressé dans le dossier (ou installé) on peut compiler un programme avec la commande :
<code lang=bash>./gavrasm <fichier_source_asm></code>
par exemple dans mon cas :
<code lang=bash>./gavrasm hello.ftdi.44.blink.asm</code>
j'arrive à compiler mon code, mais la led ne clignote pas...
;ldi temp, 255; max
;clr temp
delay_loop:----------------------------------------------- dec temp | clr temp1 | delay_loop2:-------------------------------- | dec temp1 | | clr temp2 | |2x( 255 X 3 X 255 X 255) delay_loop3:------------------ |3X255X255 | dec temp2 |1X255 | | brne delay_loop3 ------------ | | brne delay_loop2 -------------------------- | brne delay_loop---------------------------------------
ret
le clignotement est apparent et dure à peu près la durée prévue. J'ai donc fait des erreurs de calcul?
====désynchronisation====
donc un cycle dure = 1/78125 = 0,0000128 sec = 12,8 microsecondes
Finalement l'option "-i" ne donne rien, mais j'ai fini par trouver [http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=75867 une solution ici] : utiliser l'option -B 1024 pour effacer le programme(c'est l'option bitclock period)
ouf !
rcall delai; delay</code>
et ça marche !!!!!
[[image:Blink.asm.gif]]
[[Fichier:Hello.ftdi.44.blink.asm.zip]]
===en C===
Pour faire un peu plus simple, je vais essayer de programmer le bouton en C.
les pins :
* PA7 : le bouton (à mettre en pullup)
* PB2 : la led
quelques ressources utiles :
* pour comprendre les entrées sorties http://avrbasiccode.wikispaces.com/
====délai variable====
Mon programme permettra de régler le rythme de clignotement de ma led à l'aide du bouton.
Pour cela, j'ai besoin de faire un délai variable.
Lorsqu'on appuie sur le bouton, on incrémente un compteur qui servira pour le délai de clignotement de la led :
<code lang=c> ...
while (1) {
if (PINA & button_pin_in){//if button not pushed
PORTB |= led_pin_out; // Turn LED on
long_delay_ms(blink_delay);
PORTB &= ~led_pin_out; // Turn LED off
long_delay_ms(blink_delay);
}else{//if button pushed
blink_delay=10;
while(!(PINA & button_pin_in)){
blink_delay+=10;
_delay_ms(10);
}
}
}
...</code>
La fonction de base "_delay_ms" est certes plus pratique à utiliser qu'en assembleur, mais elle ne prend que des constantes, pas de variables.
pour gérer un délai variable je me suis inspiré de cette page http://www.instructables.com/id/Honey-I-Shrunk-the-Arduino-Moving-from-Arduino-t/step2/Our-first-AVR-C-project-Hello-world-LED/ en créant une fonction long_delay :
<code lang=c>
void long_delay_ms(uint16_t ms) {
for(ms /= 10; ms>0; ms--) _delay_ms(10);
}
</code>
[[Fichier:Hello.blink.button.44.zip|Mon programme]]
Mon programme fonctionne plutôt bien, mais pour qu'il fonctionne mieux, je devrais attacher une interruption au bouton, car lorsque la led est dans sa phase de clignotement, le bouton est inactif.
mais je manque de temps pour implémenter ça cette semaine
à suivre...
===avec arduino===
Comme récréation, j'essaye la librairie de [http://highlowtech.org/?p=1695 highlowtech] pour programmer les tiny directement depuis l'interface arduino.
====fondu de led réglable====
le but du programme est de régler la luminance de la led en appuyant plus ou moins longtemps sur le bouton :
<code lang=c>/*
set the value of the led by pushing the button more or less longtime
This example code is in the public domain.
led : 8
button : 7
*/
#define led 8
#define bton 7
int value;
void setup() {
value=0;
pinMode(led, OUTPUT);
pinMode(bton, INPUT_PULLUP);
}
void loop() {
if (digitalRead(bton)==LOW){
if (value!=0){
value=0;
}
else{
while(digitalRead(bton)==LOW){
if (value<255) {
value++;
analogWrite(led,value);
delay(40);
}
}
}
}
analogWrite(led,value);
delay(40);
}
</code>
j'ai constaté que le délai ne correspond pas tout à fait à ce qui est codé, comme si l'horloge était multipliée : mon délai de 40ms dure en pratique environ 200ms.
==tentative sur smoothieboard==
Pour explorer une programmation plus évoluée, j'imagine essayer de programmer de vrais fins de course sur le smoothieboard.
[http://smoothieware.org/ Cette carte de pilotage de machines CNC] équipe la plupart des machines de notre atelier et j'aimerais la faire évoluer, particulièrement pour piloter notre router grand format : [[SentierBattu]].
Une des fonctionalités qui nous fait défaut est une vraie implémentation des fins de course.
===analyse du programme===
Actuellement, le programme en C++ qui pilote cette carte est construit de façon modulaire :
[[Image:Smoothie.modules.jpg]]
je voudrais rajouter une interruption sur les fins de course, qui bloque ou inverse les steppers.
queqlues infos sur les interruptions : http://www.edaboard.com/thread196143.html
En fait Arthur, qui développe le programme m'a déconseillé d'utiliser les interuptions au risque de tout casser. De plus, il semblerai que les pins sur lesquels sont branchés les fins de course ne soit pas utilisables avec les interruptions.
Je décide alors de tenter une méthode qui peut risquer de ralentir un peu les mouvements :
implanter un appel dans la fonction
<code lang=c>Stepper::trapezoid_generator_tick</code>
Cette fonction gere les mouvements coordonnés des moteurs pas à pas. elle est appelée tout au long des mouvements.
Interroger ici les fins de course ralentira peut-être le mouvement, mais permettra d'être au plus proche des déplacements des axes, pour réagir vite en cas de dépassement des fins de course.
Cette fonction ne s'execute qu'à certaines conditions :
<code lang=c>if(this->current_block && !this->paused && this->main_stepper->moving ) {...</code>
j'insère alors au début de cette fonction :
<code lang=c> if( THEKERNEL->endstops->overflow()){//if an endstop is touched
this->current_block->release();
}</code>
et dans l'objet Endstops, je décris la fonction :
<code lang=c>
bool Endstops::overflow(){
for ( char c = 'X'; c <= 'Z'; c++ ) {
//if endstop hit and motor go in is direction
if ( this->pins[c - 'X' + (this->steppers[c - 'X']->dir_pin.get() ? 0 : 3)].get() ) {
return true;
}
}
}
</code>
Cette fonction aurai put marcher, mais je n'ai pas très bien compris la notion de modules en C++ : apparement, on ne peut appeler un module depuis un autre.
Donc cet appel croisé ne fonctionne pas. Lorsque j'ai demandé de l'aide sur l'IRC de smoothiware, je me suis fait gentillement renvoyé à mon bac à sable, notament car un des développeurs principaux est entrain d'implémenter les fins de course.
J'ai donc laissé là cette expérimentation. Cela-dit, cette recherche m'a permis de comprendre dans les grandes lignes comment fonctionne ce programme et comment contribuer au développement d'un logiciel libre (à savoir, notamment se tenir au courant des points sur lesquels travaillent les autres développeurs).
[[Catégorie:FabAcademy]]
[[Catégorie:Electronique]]