Ik ben een novice AVR programmeur, maar heb wel redelijk veel ervaring met programmeren onder Windows/Unix.
Ik wil met een Tiny45 een motortje aansturen. Ik heb in dat kader een L293(E) op de 45 aangesloten.
Ik wil graag een schakelaar tussen PB0 en GND hangen. Als ik de motor linksom heb draaien dan moet met een druk op de knop de draairichting veranderen.
Ik heb de L293 aan PB3 en PB4 hangen.
De volgende C-code wordt in de Tiny45 geladen:
void init()
{
DDRB = 0x00111000; // PORTD PB3-PB5 als uitgang, rest ingang
PORTB = 0x00000000; // PORTD PB0-PB5 alle uitgangen laag
//DDRB = 0; // PORTB PB0-PB7 volledig als ingang
PORTB = (1 << PB0); // PB0 pull-up aan
PCMSK = (1 << PCINT0); // activeer PCINT0 (PB0) voor pin-change detectie
GIMSK = (1 << PCIE); // schakel pin-change interrupt in
}
int main()
{
init();
int richting = 1; // vooruit = 1, achteruit = 0
while(1)
{
if (bit_is_set(PINB, PB0)) {
if (richting == 1) {
richting = 0;
PORTB = (1 << PB4) | (0 << PB3);
delay(20); // even zou houden tegen input
} else {
richting = 1;
PORTB = (0 << PB4) | (1 << PB3);
delay(20); // even zou houden tegen input
}
} else {
if (richting == 1) {
PORTB = (1 << PB4) | (0 << PB3);
} else {
PORTB = (0 << PB4) | (1 << PB3);
}
}
}
return 0;
}
De motor 'stottert' als ik de pin PB0 niet met grond verbind (dus komt hij toch in de bovenste if), als ik deze verbind dan draait de motor. Polariteit wordt niet omgekeerd alleen.
Van de L293E zijn poorten 1..10 aangesloten
1 en 10 naar de 5V
2 en 9 naar resp PB4 en PB3 van de Tiny45
3 en 8 naar de motor (moet eigenlijk via diodes, maar is klein motortje, vooralsnog zo even testen)
Sense is niet aangesloten (dat zou er mee te maken kunnen hebben?!)
GND op 5 en 6 is aangesloten op GND van het circuit.
Bedankt voor moeite/input en prettige kerstdagen
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Een kleine voorzet alvast. Ik ben niet bekend met de L293 en heb ook nog niet de moeite genomen daar de datasheet van te zoeken. Ik zie wel drie problemen in je C code.
Ten eerste de declaratie van de registers, daar gebruik je een bitgewijze notatie, met een hexadecimaal voorvoegsel. 0x is altijd een hexadecimaal getal, voor bitgewijs gebruik je 0b. Deze notatie geeft ook een compiler warning 'large integer implicitly truncated to unsigned type' Code die compiler warnings geeft is altijd verdacht.
Dan PB0, eerst doe je PORTB = (1 << PB0); om de pull-up te activeren. Dat is prima. Maar de eerstvolgende keer dat je PORTB wijzigd met PORTB = (1 << PB4) | (0 << PB3); overschrijf je deze waarde en is de pull-up niet meer actief. Je kan dat oplossen door per bit te activeren/deactiveren PORTB |= (1 << PB4); PORTB &= ~(1 << PB3);
Waarom schakel je het pin-change interrupt in terwijl je het niet gebruikt?
ik heb er nu dit van gemaakt, maar nog geen resultaat:
int main()
{
init();
int richting = 1; // vooruit = 1, achteruit = 0
while(1)
{
if (bit_is_set(PINB, PB0)) {
if (richting == 1) {
richting = 0;
set_PORTB_bit(PB4,1);
set_PORTB_bit(PB3,0);
delay(20); // even zou houden tegen input
} else {
richting = 1;
set_PORTB_bit(PB4,0);
set_PORTB_bit(PB3,1);
delay(20); // even zou houden tegen input
}
} else {
if (richting == 1) {
set_PORTB_bit(PB4,1);
set_PORTB_bit(PB3,0);
} else {
set_PORTB_bit(PB4,0);
set_PORTB_bit(PB3,1);
}
}
}
return 0;
}
motor draait 1 kant uit, geen reactie als ik pb0 hoog maak.
Je staat continu bits te setten. Dat is overbodig. Doe dat 1x, een AVR is prima in staat om ze zo te houden.
Tevens doe je het niet consequent. Stel dat je 'richting' van 0 naar 1 gaat, dan zet je PB4 0 en PB3 1. Als je dan je button los laat, zet je PB4 1 en PB3 0. Dat levert wat geklapper op.
Zou het kunnen dat je voeding voor je AVR niet fatsoenlijk in elkaar zit en het ding op dat geklapper reset? (schema?)
Ik ken die bridge niet (en heb ook geen zin om me erin te verdiepen), maar iets zegt me dat je eerst alles uit moet zetten en dan aan wat nodig is. Anders heb je. mi. een volle sluiting.
Zou het kunnen dat je dat nu doet en dat je AVR gewoon consequent staat te resetten agv. een klapperende voeding? (post eens een schema!)
Verder doet je code vermoeden dat er op PB0 een pull-down zit met een schakelaar naar de +. Als dat niet zo is, zou dat ook nog wel eens bron van je probleem kunnen zijn. Wederom: post een schema.
Hier is het schema, ISP verbindingen missen, maar die zijn wel ok aangezien hij keurig programmeert.
Ik heb de buitenste ELSE leeggemaakt (ik wist niet of de motor gewoon door zou gaan met lopen, vandaar, maar idd is het een kwestie van pinnen setten en dat zou idd gewoon door moeten blijven gaan, ik programmeer normaal met RobotC en zo als ik hardware aanstuur en daar werkt dat nog wel eens anders).
Rondje stelt motor voor, kon zo even de aansluitpunten niet vinden voor 5V en GND, maar is op dit moment op breadboard.
Niet om te zeuren maar dat is nog niet echt een schema. Voor diegene die de L293 niet kent moet nu nog steeds de datasheet erbij halen. Dit is een schema :
Groeten, Bram
Op 25 december 2008 11:44:37 schreef bprosman:
Niet om te zeuren maar dat is nog niet echt een schema. Voor diegene die de L293 niet kent moet nu nog steeds de datasheet erbij halen. Dit is een schema :Groeten, Bram
(Ik snap nu dat het om het je 'principe' ging)
Overigens had ik alleen de beschikking over de L293E en die wijkt nogal af (sense pen is leeg in mijn geval, wellicht levert dat problemen op). (eagle heeft dat ding ook niet, alleen de veel handigere, maar moeilijker voor mij te krijgen L293D).
B.t.w. gedrag is nu dat het motortje pendelt tussen links/rechts, tenzij PB0 aan 5+ geschakeld wordt, maar komt dus in de goede richting, nu een kwestie van debuggen.
Na nogal wat libraries etc. toegevoegd te hebben, heb ik het voor elkaar:
int main()
{
init();
int richting = 1; // vooruit = 1, achteruit = 0
while(1)
{
if (bit_is_set(PINB, PB0)) {
if (richting == 1) {
richting = 0;
set_PORTB_bit(PB4,1);
set_PORTB_bit(PB3,0);
delay(20); // even zou houden tegen input
} else {
richting = 1;
set_PORTB_bit(PB4,0);
set_PORTB_bit(PB3,1);
delay(20); // even zou houden tegen input
}
}
}
return 0;
}
'hij' komt dus blijkbaar altijd in de lus, TENZIJ ik de knop in druk... vreemd, simpel op te lossen door een not bij de if, maar dan nog... bit_is_set levert dus niet het resultaat op wat je zou verwachten?! Blijkbaar set ik de instellingen voor PB0 niet helemaal goed.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#ifndef F_CPU
#define F_CPU 8000000UL /* interner RC mit 8 Mhz */
#endif
// Function prototype
int set_PORTB_bit(int position, int value);
/*
1 = PB5 / Schalter Bit 4
2 = PB3 / Schalter Bit 3
3 = PB4 / Schalter Bit 2
4 = GND
5 = OC0A / PWM Ausgang
6 = PB1 / Schalter Bit 1
7 = ADC1 / Eingang
8 = VCC
*/
void init()
{
DDRB = 0b00111000; // PORTD PB3-PB5 als uitgang, rest ingang
PORTB = 0b00000000; // PORTD PB0-PB5 alle uitgangen laag
}
void delay(unsigned char t)
{
while(t)
{
_delay_ms(8);
t--;
}
}
// Function code
int set_PORTB_bit(int position, int value)
{
// Sets or clears the bit in position 'position'
// either high or low (1 or 0) to match 'value'.
// Leaves all other bits in PORTB unchanged.
if (value == 0)
{
PORTB &= ~(1 << position); // Set bit position low
}
else
{
PORTB |= (1 << position); // Set high, leave others alone
}
return 1;
}
int main()
{
init();
int richting = 1; // vooruit = 1, achteruit = 0
while(1)
{
if (bit_is_set(PINB, PB0)) {
if (richting == 1) {
richting = 0;
set_PORTB_bit(PB4,1);
set_PORTB_bit(PB3,0);
delay(200); // even zou houden tegen input
} else {
richting = 1;
set_PORTB_bit(PB4,0);
set_PORTB_bit(PB3,1);
delay(200); // even zou houden tegen input
}
}
}
return 0;
}
Werkt nu goed met schema zie boven. Init deed inderdaad nog wat dingen die in dit geval niet moesten.
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Op PB0 gebruik je een pull-up en met een schakelaar schakel je deze naar VCC. Door de pull-up heeft PB0 altijd al een positief niveau, oftwel een digitale 1. Het bedienen van de schakelaar zou dan geen enkel effect hebben want 1 is al 1. Logisch zou zijn om de schakelaar naar GND te schakelen. Standaard is de PB0 dan 1 en bij het bedienen van de schakelaar gaat deze naar 0.
Op 25 december 2008 13:37:12 schreef Marcel:
Op PB0 gebruik je een pull-up en met een schakelaar schakel je deze naar VCC. Door de pull-up heeft PB0 altijd al een positief niveau, oftwel een digitale 1. Het bedienen van de schakelaar zou dan geen enkel effect hebben want 1 is al 1. Logisch zou zijn om de schakelaar naar GND te schakelen. Standaard is de PB0 dan 1 en bij het bedienen van de schakelaar gaat deze naar 0.
Aangezien ik de pull-up uit de Init gehaald heb, werkt het nu zoals in het schema staat.
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Maar je hebt ook geen pull-down, dus een gegarandeerd 0 niveau is er niet. Dat is namelijk het doel van een pull-up of pull-down, het niveau bepalen wanneer de schakelaar niet bediend wordt. Nu zweeft de pin.
Op 25 december 2008 13:54:03 schreef Marcel:
Maar je hebt ook geen pull-down, dus een gegarandeerd 0 niveau is er niet. Dat is namelijk het doel van een pull-up of pull-down, het niveau bepalen wanneer de schakelaar niet bediend wordt. Nu zweeft de pin.
hmm ok, nou dan is dat wel belangrijk dus! dank je!
Pull-down is dan dus gewoon 0 naar die poort schrijven?
PORTB = (0 << PB0);
[Bericht gewijzigd door JopieK op (12%)]
Met die opmerking van Marcel erbij, begint het ergens heen te gaan.
Wat me nog wel zorgen baart, is de voeding. Je voedt de Tiny uit dezelfde voeding als je motor. Er zit geen enkele ontkoppeling bij. Dit is vragen om spontane resets / ongedefinieerd gedrag.
Vergis je niet in de rommel die zelfs een klein motortje op z'n voeding kan veroorzaken. Zeker bij het omschakelen (ding trekt dan even fors stroom), maar ook een wat knetterende koolborstel doet het soms leuk.
Zorg dat die L-doe-wat-leuks z'n eigen 5V heeft en die dus niet deelt met je AVR en zorg voor een ontkoppel Ctje over de voeding van de AVR.
Verder zijn in reset alle pins van die AVR floating. Zou dat kunnen betekenen dat er ongedefinieerde nieau's op je motor driver zouden kunnen staan? Zou dat kunnen betekenen dat het ding in sluiting komt?
Qua storingsgevoeligheis is schakelen naar 0 zowiezo handiger. Ik zou pull-up doen en schakelaar naar GND.
Groeten, Bram
Op 25 december 2008 14:25:08 schreef Marco69:
Met die opmerking van Marcel erbij, begint het ergens heen te gaan.Wat me nog wel zorgen baart, is de voeding. Je voedt de Tiny uit dezelfde voeding als je motor. Er zit geen enkele ontkoppeling bij. Dit is vragen om spontane resets / ongedefinieerd gedrag.
Vergis je niet in de rommel die zelfs een klein motortje op z'n voeding kan veroorzaken. Zeker bij het omschakelen (ding trekt dan even fors stroom), maar ook een wat knetterende koolborstel doet het soms leuk.Zorg dat die L-doe-wat-leuks z'n eigen 5V heeft en die dus niet deelt met je AVR en zorg voor een ontkoppel Ctje over de voeding van de AVR.
Verder zijn in reset alle pins van die AVR floating. Zou dat kunnen betekenen dat er ongedefinieerde nieau's op je motor driver zouden kunnen staan? Zou dat kunnen betekenen dat het ding in sluiting komt?
Ik zet het uiteindelijke ding op 9V, inmiddels heb ik dat ook getest, die L293E heeft helaas extra diodes nodig (maar ik vervang 'm dus ws. door een D, dit is alleen even voor het experiment).
Over de opmerking over 0 en pull-up. pull-up heeft te maken met de rijzende flank toch? Als die gedetecteerd wordt geeft de poort/pin een interrupt.
In de uiteindelijke schakeling zal ik er ook een condensator bij doen
Over de opmerking over 0 en pull-up. pull-up heeft te maken met de rijzende flank toch? Als die gedetecteerd wordt geeft de poort/pin een interrupt.
Die moet je even uitleggen... Als het spul op een rising edge al een IRQ zou genereren, zou je dat aan moeten zetten en een ISR moeten klussen. Het enige wat ik jou zie doen, is die pin pollen.
Marcel
AVR C tutorial http://expand.xs4all.nl/avr
Op 25 december 2008 14:02:22 schreef JopieK:
Pull-down is dan dus gewoon 0 naar die poort schrijven?PORTB = (0 << PB0);
Nee, lees de datasheet er nog eens op na. Een AVR heeft alleen interne pull-ups. Wat je dan doet is juist de pull-up deactiveren. Een pull-down zal je zelf extern moeten aanbrengen. Maar in dat geval is het handiger om het om te draaien en de schakelaar naar GND te schakelen zodat je de interne pull-up kan gebruiken.