Gå til innhold

Den lille Arduino-tråden


Anbefalte innlegg

Videoannonse
Annonse

Hvordan kjører jeg flere programmer samtidig? hvis jeg har 4 led lys som skal være tids innstilt, også har jeg 4 andre som skal reagere på en Photocelle? sjønner?

 

Enkleste måte:

Legge alt sammen inne i while-loopen som utgjør programmet med noen enkle sjekker for om noe skal gjøres eller ikke... Problemet vil bli at loopen vil bruke forskjellig antall klokkesykler avhengig av hva som skal utføres per loop (kan eventuelt lage en sjekk på slutten for å kompensere for dette).

 

Mer saklig måte å gjøre dette på:

Bruke en timer til å generere interrupts for tidsinnstilte LEDs, og bruke IO/PIN interrupt for LEDs som skal reagere på photocellene.

 

Avansert:

Kjøre RTOS på AVRen for å kunne kjøre flere oppgaver samtidig.

 

Snakke om antall kjerner, 8 eller 32 bit og slik har veldig lite med saken å gjøre. Problemet er det samme uansett, og det kan fint løses på en 8bits AVR på flere måter som nevnt over. RTOS har jeg ikke prøvd selv, men interrupt er en ganske grei og enkel sak egentlig (og om du ikke kan det er det nå et fint tidspunkt å lære det på :) )

Lenke til kommentar

Godt spørsmål. Eg tror ikke det, men er litt usikker.

 

Når du skal programmere den via serieporten(som går via USB-porten til maskinen) så vil mikrokontrolleren først resettes. Og mens bootloaderen starter opp er det noen sekunder hvor den er mottakelig for programmering, før den fortsetter om den ikke mottar data. Og om den mottar data i dette tidsrommet så tar den i mot ny kode som den legger inn. Eg tror ikke portoppsettet aktiveres før etter dette tidspunktet.

 

Uansett så har du muligheten for å programmere den via ISP, men det krever litt ekstra utstyr, eller en Arduino nr to :)

 

 

Programmering vil fungere helt fint. Det er som nomore sier et lite tidsrom hvor kontrolleren venter på beskjed om den skal gå inn i bootloaderen eller ikke før den går videre i programmet og koden du har skrevet starter.

 

Takk for svar :) jeg kikket litt mer nå på hva jeg har gjort til nå og ser faktisk at jeg hele tiden har programmert RX og TX (port D, pinne 0 og 1) som utganger :D uten at det har hindret meg i å programmere om igjen etterpå. Så da er det bare fritt fram å leke seg.

Lenke til kommentar

Kommer med et lite fillespm. nå. Jeg forsøker å få den Arduino'en til å telle antall ganger jeg trykker på en knapp, men får den ikke til å telle.

 

Har forsøkt diverse. Har laget noen andre telle-løkker som den teller uten problemer, men å telle antall input funka dårlig. Noen som har en ide?

 

 

Koden jeg bruker er lagt ved under.

int pause2 = 150;
int i, j = 0;
int teller = 0;
int input;

void setup()
{
DDRD = B11111111;  // Initialiserer Port D som utgang.
DDRB = B00001111;  // Initialiserer Port B, pinne 0-3 som utgang, pinne 4-7 som inngang.
PORTD = B00000000; // Setter Port D logisk 0
}

void loop() { // Main

input = digitalRead(13);
teller = teller + input;
if (teller > 2)
teller = 0;

if ( teller == 1 ) { // Dersom knapp trykkes inn.. 
 for ( i = 0; i < 9; i++) {  // For-løkke som teller lampene 1-9.
   digitalWrite(i, HIGH);    // Tenner alle lampene.
 }
} 
else {                        // Dersom knapp ikke er trykket inn..
 PORTD = B00000000;          // Setter Port D logisk 0
 PORTB = B00000000;          // Setter Port B logisk 0
 digitalWrite(j, HIGH);      // Tenner lampen i har telt til.
 delay(pause2);              // Opphold.
 digitalWrite(j, LOW);       // Slukker lampen i har telt til.


 j = j + 1;
 if ( j > 9 )
  j = 0;
}
}

Lenke til kommentar

Jeg forsøker å få den Arduino'en til å telle antall ganger jeg trykker på en knapp, men får den ikke til å telle.

input = digitalRead(13);

 

 

Er det knappen som orginalt sitter på kortet eller er den knappen du nevner tilkoblet pinne 13 ?

 

Har ikke programmert noe serlig arduino, men syslet lit med selvlagde kort med ATmega. Der legger jeg gjerne inngangen høy hvis knappen går til gnd

 

DDRB = B00001111;

PORTB = B00001111; Seteer inngang høy ( pull up resistor )

Lenke til kommentar

Liten kodebit fra ett vellyket forsøk med tre tellere, tre knapper for telling opp og tre knapper for telling ned.

Ligger forsinkelser andre steder i programmet for å holde telletempo moderat.

 

DDRB = 0x00;

PORTB =0xFF ;

 

if (bit_is_clear(PINB,PINB0)){

teller1++;

Lenke til kommentar

Jeg forsøker å få den Arduino'en til å telle antall ganger jeg trykker på en knapp, men får den ikke til å telle.

input = digitalRead(13);

 

 

Er det knappen som orginalt sitter på kortet eller er den knappen du nevner tilkoblet pinne 13 ?

 

Har ikke programmert noe serlig arduino, men syslet lit med selvlagde kort med ATmega. Der legger jeg gjerne inngangen høy hvis knappen går til gnd

 

DDRB = B00001111;

PORTB = B00001111; Seteer inngang høy ( pull up resistor )

 

Ja, har koblet en knapp til pinne 13 som skal gi logisk 1 når jeg trykker. Har kjørt noen andre kodesnutter med knappen, men da måtte den holdes inne så lenge endringen varte. Det fungerte fint :)

 

Ideen var å gi programmet 2 funksjoner som man kan svitsje mellom ved å gi knappen et lite trykk.

 

Forestilte meg at det kunne realiseres ved å telle antall ganger jeg trykker og få programmet til å resette telleren når den kommer til 2 (da jeg trenger bare 0 og 1)

 

Korrigering: La merke til at jeg har brukt feil tall for å resette telleren. Skal være 1, ikke 2. Uten at dette har betydning for at den ikke vil telle antall trykk.

 

pinne 0-8 styrer en rekke LED's (

 

Er ikke "bit_is_clear(PINB,PINB0)" intruksjoner tilhørende mikrokontrollerne i PIC-familien?

 

EDIT:

if ( digitalRead(13) == HIGH)
 teller = teller + 1;
if (teller > 1)
 teller = 0;

Burde ikke denne snutten fungert under alle omstendigheter?

Og så bruker teller for å skille mellom ønskede funksjoner.

Endret av janingar
Lenke til kommentar

Nøyaktig hvordan har du koblet opp bryteren? Hvis du bare har koblet den mellom positiv supply og pinne 13, har du da en motstand som drar linjen lav når du ikke trykker knappen nede? Du må sørge for at linjen alltid er definert (dvs koblet til positive eller negativ supply på en eller annen måte). Jeg ville valgt å bruke de interne pull-up motstandene, og koblet bryteren mellom pinne 13 og jord.

 

Debouncing må du nesten ha, når du trykker ned knappen kan det fort registreres som flere trykk avhengig av hvor rask loopen din er.

 

Angående koden, dette skjer:

- teller er 0

- knapp trykkes, teller blir 1, alle leds tennes

- null delay, du har enda ikke sluppet knappen, teller blir satt til 0, alle led slukkes.

- led j tennes og lyser i 150 (ms?) og slukkes igjen...

- knappen blir sluppet og hver av leddene blinker i 150 (ms?) etter hvert som j økes.

 

Tipper at koden utføres korrekt, men at det går for for til at du rekker å se hva som skjer.

 

Prøv å legge inn delay på alle stedene og se om du da klarer å se hva som skjer.

 

Hvis du bare vil telle antall ganger en knapp er telt så ville jeg gjort det litt annerledes:

 

int knapp_trykk = 0; //programmets tilstand
int knapp_tilstand_d1 = 0; //forrige leste verdi
int teller = 0;  //antall trykk

void loop() {

 //les knapp
 knapp_tilstand_d1 = digitalRead(13);  
 //enkel debouncing ved å sjekke at knappen fremdeles er trykket
 //(noen klokkesykler senere) og at knappen ikke var registrert som trykket fra før.
 if(knapp_tilstand_d1 && digitalRead(13) && !knapp_trykk) { 
   knapp_trykk = 1; //knappen er nå trykket.
   teller++;  //øk teller
 }
 else if(!knapp_tilstand_d1 && !digitalRead(13) && knapp_trykk){
   knapp_trykk = 0; //knappen ble sluppet
 }

 //set leds her...
 PORTB = teller; //eller noe slikt
}

 

Koden er sikkert ikke perfekt, skrevet i halvsøvnet her, men du ser kanskje hovedideen bak? Du må ha en tilstand i programmet som sier om knappen er trykket eller ikke for å kunne garantere korrekt deteksjon av trykk (unngå dobbel trykk o.l.)

Endret av Dr_VingTor
Lenke til kommentar

Hei folkens!

 

Holder på med et lite (nybegynner) prosjekt hvor jeg har tenkt å lage en liten fjernkontroll som skal styre blinklys (går på 2-pinner, en LED-farge til hver pinne), frontlys (2 led som skal lyse) og en sirene.

 

Jeg får sendt ut et digitalt HIGH signal fra et Xilinx-kort som da "styrer" kretsen (hører til en større krets med motordrivere osv) så jeg ville da ha min arduino til å kjøre blinklys, hovedlys og sirene når denne får HIGH kommandoen.

 

Jeg har skrevet en kode med If-tester som skal kjøre alle mine 3 funksjoner når den får inn et HIGH signal, men jeg får da et lite problem med min sirene. Lysene fungerer ganske greit, men sirenen kjører av seg selv av og til, mens den andre ganger er helt stille til jeg trykker inn en test knapp. Selve sirenekoden har jeg bygd ut ifra en mal som kommer med arduinoen da mine C kunnskaper er begrensede.

 

Jeg mistenker at det kan være for-funksjonen som kødder litt, er det noen som har noen tips på hva som evt kan være problemet mitt?

 

#include "pitches.h"

 

const int buttonPin1 = 2; //blink

const int buttonPin2 = 3; //hovedlys

const int buttonPin3 = 4; //sirene

 

const int outPin1 = 6; //ut til blålys RØD

const int outPin2 = 7; //ut til blålys BLÅ

const int outPin3 = 8; //ut til hovedlys

const int outPin4 = 9; //sirene

 

 

 

int buttonState = 0; // current state of the button

int lastButtonState = 0;

int buttonState2 = 0; // current state of the button

int lastButtonState2 = 0;

int buttonState3 = 0; // current state of the button

int lastButtonState3 = 0;

 

 

void setup() {

 

pinMode(2, INPUT);

pinMode(3, INPUT);

pinMode(4, INPUT);

//pinMode(5, INPUT); ubrukt

pinMode(6, OUTPUT);

pinMode(7, OUTPUT);

pinMode(8, OUTPUT);

pinMode(9, OUTPUT);

 

Serial.begin(9600);

}

 

void loop() {

buttonState = digitalRead(buttonPin1);

lastButtonState = buttonState;

buttonState2 = digitalRead(buttonPin2);

lastButtonState2 = buttonState2;

buttonState3 = digitalRead(buttonPin3);

lastButtonState3 = buttonState3;

 

 

if (buttonState == HIGH) {

Serial.println("Button just pressed");

 

digitalWrite(outPin1, HIGH);

delay(150);

digitalWrite(outPin1, LOW);

delay(150);

digitalWrite(outPin2, HIGH);

delay(150);

digitalWrite(outPin2, LOW);

delay(150);

 

}

 

if (buttonState == LOW) {

digitalWrite(outPin1, LOW);

digitalWrite(outPin2, LOW);

 

}

if (buttonState2 == HIGH){

Serial.println("Button just pressed");

digitalWrite(outPin3, HIGH);

}

 

if (buttonState2 == LOW) {

Serial.println("Button just pressed");

digitalWrite(outPin3, LOW);

 

}

if (buttonState3 == HIGH) {

 

Serial.println("Button just pressed");

 

int melody[] = {

NOTE_D5, NOTE_A5, NOTE_D5, NOTE_A5, NOTE_D5, NOTE_A5, NOTE_D5};

 

// note durations: 4 = quarter note, 8 = eighth note, etc.:

int noteDurations[] = {

2, 2, 2, 2, 2, 2, 2, 2 };

 

// iterate over the notes of the melody:

for (int thisNote = 0; thisNote < 8; thisNote++) {

 

// to calculate the note duration, take one second

// divided by the note type.

//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.

int noteDuration = 1000/noteDurations[thisNote];

tone(9, melody[thisNote],noteDuration);

 

// to distinguish the notes, set a minimum time between them.

// the note's duration + 30% seems to work well:

int pauseBetweenNotes = noteDuration * 1.00;

delay(pauseBetweenNotes);

// stop the tone playing:

noTone(9);

}

}

 

/* if (buttonState3 == LOW) {

 

digitalWrite(outPin4, LOW); } */

 

 

}

 

 

Endret av Sisyphus
Lenke til kommentar

Har du koblet inngangene til jord med en pulldown-motstand? Dette må du gjøre slik at inngangene konsekvent er 0 frem til de får signal(5v som regel). Dersom du ikke gjør det kan krypstrøm gjøre at en inngang trigger high selv om det er kun i millisekunder.

Lenke til kommentar

10k er mye brukt hos meg på 5v som pulldown. Men den skal kobles mellom inngangen og signalet inn(fra Xilinx) og jord. Da vil signalet inn være 0v frem til Xilinx sier noe annet. Om du ikke gjør det vil inngangen flyte, som det heter, og det kan være nok til å gi high som trigges i koden din.

 

Noe alla dette: rain-one-sensor-circuit-diagram.png

 

Det som er merket PIR der er Xilinx'en din.

  • Liker 1
Lenke til kommentar

Har hevet meg på bølgen og startet med ett lite prosjekt selv.

 

Planen er at jeg skal styre en Curtis 1225 fra RC fjernstyring, kunne gjort det med servoer, pot meter og brytere, men det er ikke gøy

 

Curtis 1225 Datasheet

 

Fant en fin kode fra denne karen: http://www.rediculouslygoodlooking.com/ og hans Lawnbot400 og har jobbet videre med denne.

 

Har så langt:

- endret dødband, der PWM starter på 0 når programmet setter FWD/ REV

- forandret fra H bridge til FWD/ REV + PWM (som skal igjennom lavpass filter og bli til 0-5V)

- Lagt til LCD med div info, skal utbedres

 

Er fermdeles mye rot i koden da den er under konstant utbedring

 

Det jeg sliter med er å få en bedre overgang fra Stopp til FWD/ REV og tilbake igjen til stopp. Hvis stikken er i kanten på dødbandet kan den hoppe fra stopp til FWD/ REV og tilbake ganske fort, dette vil neppe Curtisen like noe godt. Vil ha en lite tids forsinkelse men den skal ikke forsinke hele loopen....

 

Noe forslag?

 

/* Code basede on code found at www.rediculouslygoodlooking.com

Read PPM signals from 1 channel of an RC reciever and convert the values to PWM in either direction.
DP 5 PWM for control motor1 (Add low pass filter to get 0-5V) 
DP 13 are neutral indicator lights. 
DP 8 Forward signal
DP 7 Revers signal
DP 2 input from the R/C receiver. 
All analog pins are open. 

 LCD
 The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 10
* LCD D5 pin to digital pin 6
* LCD D6 pin to digital pin 4
* LCD D7 pin to digital pin 3
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 10, 6, 4, 3);

//PWM Pins
int motor1_a = 5; // motor 1 outputs

//Control pins
int motor1_fwd = 8; //motor 1 fwd
int motor1_rev = 7; //motor 1 rev

//Indicator leds
int ledPin1 = 13; //neutral

//RC Input
int servo1 = 2;  // r/c channel 1

//Other variables
String dir = ("   "); 
unsigned int relay_val;
volatile unsigned long servo1_startPulse;  //values for channel 1 signal capture
volatile unsigned servo1_val; 
volatile int adj_val1;  
volatile int servo1_Ready;
int pwmMotor1 = 0;

int deadband_high = 256; //280
int deadband_low = 254;  //230

int pwm_ceiling = 256; 
int pwm_floor = 254;  

int low1 = 1120;  // adjust these values if your R/C readings are above or below these for channels 1 and 2.
int low1h = 1500; // changes from stop to rev

int high1l = 1560; // changes from stop to fwd
int high1 = 1910;

int n = 0;

void setup() {

 // set up the LCD's number of columns and rows: 
 lcd.begin(16, 2);
 lcd.print("Curits RC");
 lcd.setCursor(0, 1);
 lcd.print("wait");

 //TCCR0B = TCCR0B & 0b11111000 | 0x03;
 //TCCR1B = TCCR1B & 0b11111000 | 0x01;

 Serial.begin(9600);

 //motor1 pins
 pinMode(motor1_a, OUTPUT);
 pinMode(motor1_fwd, OUTPUT);
 pinMode(motor1_rev, OUTPUT);

 //led's
 pinMode(ledPin1, OUTPUT);

 //PPM inputs from RC receiver
 pinMode(servo1, INPUT); //Pin 2 as input

 delay(1200);

 attachInterrupt(0, rc1_begin, RISING);    // catch interrupt 0 (digital pin 2) going HIGH and send to rc1()

}

////////// attach servo signal interrupts to catch signals as they go HIGH then again as they go LOW, then calculate the pulse length.

void rc1_begin() {           // enter rc1_begin when interrupt pin goes HIGH.

 servo1_startPulse = micros();     // record microseconds() value as servo1_startPulse

 detachInterrupt(0);  // after recording the value, detach the interrupt from rc1_begin

 attachInterrupt(0, rc1_end, FALLING); // re-attach the interrupt as rc1_end, so we can record the value when it goes low

}

void rc1_end() {

servo1_val = micros() - servo1_startPulse;  // when interrupt pin goes LOW, record the total pulse length by subtracting previous start value from current micros() vlaue.

detachInterrupt(0);  // detach and get ready to go HIGH again

attachInterrupt(0, rc1_begin, RISING);

}
/////// servo interrupts end

/////// MAIN LOOP

void loop() {

///// channel 1 good signal check
if (servo1_val < 600 || servo1_val > 2400) {  // only set the servo1_Ready flag if the value is a valid Servo pulse between 600-2400 microseconds.
 servo1_Ready = false; 
 servo1_val = 1500;
}
else {
 servo1_Ready = true; // if not, don't pass the value to be processed
}


////////// channel 1 motor update	         


   if (servo1_Ready) {

     //servo1_Ready = false;  
     //adj_val1 = map(constrain(servo1_val, 600, 2400), low1, high1, 0, 511); 
     //constrain(adj_val1, 0, 511);

     servo1_Ready = false; 
    if (servo1_val < low1h)
   { 
     adj_val1 = map(constrain(servo1_val, 600, 2400), low1, low1h, 0, 255); 
     constrain(adj_val1, 0, 511);
   }

   //else if (servo1_val > 1519 || servo1_val < 1538)
   //{
   //  adj_val1 = 255;
   //}

   else if (servo1_val > high1l)
   {
     adj_val1 = map(constrain(servo1_val, 600, 2400), high1l, high1, 256, 511); 
     constrain(adj_val1, 0, 511);
   }

   else
   {
     adj_val1 = 255;
   }

     if (adj_val1 < 0) {
       adj_val1 = 0; 
     }     
     if (adj_val1 > 511) {
       adj_val1 = 511; 
     }

     if (adj_val1 > deadband_high) {
       //Forward
       //digitalWrite(motor1_b, LOW);
       digitalWrite(motor1_rev, LOW);
       digitalWrite(motor1_fwd, HIGH);
       pwmMotor1 = adj_val1 - pwm_ceiling;
       analogWrite(motor1_a, pwmMotor1);
       digitalWrite(ledPin1, LOW);
       dir = ("FWD");
     }
     else if (adj_val1 < deadband_low) {
       //REVERSE
       //digitalWrite(motor1_a, LOW);
       //analogWrite(motor1_b, pwm_floor - adj_val1);
       digitalWrite(motor1_fwd, LOW);
       digitalWrite(motor1_rev, HIGH);
       pwmMotor1 = pwm_floor - adj_val1;
       analogWrite(motor1_a, pwmMotor1);
       //analogWrite(motor1_a, adj_val1);
       digitalWrite(ledPin1, LOW);
       dir = ("REV");
     }
     else {
       //STOP
       //digitalWrite(motor1_a, LOW);
       //digitalWrite(motor1_b, LOW);
       digitalWrite(motor1_fwd, LOW);
       digitalWrite(motor1_rev, LOW);
       pwmMotor1 = 0;                 //Force PWM to 0
       analogWrite(motor1_a, pwmMotor1);    
       digitalWrite(ledPin1, HIGH); // turn on neutral light, turn motor pins off
       dir = ("STO");
     }

   }

   //print to LCD
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print(dir);
     lcd.setCursor(4, 0);
     lcd.print(adj_val1);
     lcd.setCursor(0, 1);
     lcd.print("PWM: ");
     lcd.setCursor(5, 1);
     lcd.print(pwmMotor1);


   //print values to Serial monitor in Arduino IDE
   Serial.print("ch1:  ");
   Serial.print(adj_val1);
   Serial.print("  ");
   Serial.print("rc1:  ");
   Serial.print(servo1_val);
   Serial.print("  ");
   Serial.print("FWD   ");
   Serial.print(adj_val1 - pwm_ceiling);
   Serial.print("  ");
   Serial.print("REV   ");
   Serial.print(pwm_floor - adj_val1);
   Serial.print("  ");
   Serial.print(dir);
   //Serial.print("loop counter:  ");
   //Serial.print(n);
   Serial.println("  ");    

   //n++;


}



Endret av Behydro
Lenke til kommentar

Hei

har en teat NTC 20 termistor, som jeg vil lese av med arduinoen. den er 20k ohm ved 25C. jeg prøvde å lage en spenningsdeler:

 

 

ascii skjema:

+5V - R20k - * - NTC - GND
            |
            |
            A0 

 

 

da får jeg målinger fra ca 10 til ca 40 grader,

men jeg skulle utnyttet mere av temp-båndet, så er det noen kloke hoder som kan hjelpe meg med å få det til? :hmm:

 

kan hende at det er nok å endre motstanden i spenningsdeleren, men jeg er ikke helt dreven på elektronikk, samtidig med at jeg tenker alt for vanskelig... :roll:

Lenke til kommentar

Hvordan har du gått frem for å få omgjort spenningen som kommer til A0 til temperatur?

 

det har jeg gjort med map-funksjonen

sensorValue = analogRead(sensorPin); // read analog value

  sensorValue = map(sensorValue, 0, 1023, 10, 40); // remap the input to fit the measuring scale

   if (sensorValue <= 10 )   { client.print(" < 10 "); // if lower than scale
 }
   else if (sensorValue  >= 40 ) { client.print("> 40 "); // if over scale
 }
   else {client.print(sensorValue); //print to web page
   }

Endret av haavardgj
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...