Go Down

Topic: Räknare (nybörjare) (Read 8993 times) previous topic - next topic

Uppfinnarwannabee

Hej nu har jag haft min arduino uno några månader.
Men jag har inte lyckats göra det jag köpte den för
eftersom jag inte kan ta till och lära mig den här programeringen riktigt.

Så jag undrar om någon vänlig själ kan hjälpa mig med
hur jag kan lösa följande:

jag vill ha en brytare som varje gång den slår till ger ut ett värde
dvs antal tillslag den gjort.

när den gjort ett visst antal tillslag vill jag att en annan brytare ska bekräfta
antalet tillslag på den förra och att detta värde sparas så att jag kan
kopiera in det till excel t.ex. sedan ska det hela nollställas så jag kan
börja mäta igen. (men varje mätserie ska finnas kvar och sparas eftersom)

det jag ska göra är ett sorts mätintrument med ungefär samma
princip som en cykeldator. dvs ett hjul med en magnet brytare och magnet.
men som jag själv genom att trycka in en knapp kan avsluta och "bekräfta in"
mätvärdet. nollställa och mäta nästa serie.

Hoppas jag varit tydlig nog annars får ni fråga

3dprinter

Hur mycket kan dit program nu? (Den där smörja om "How to use this forum - please read" gäller också här)

Jag gissar att du får for många "slag", pga contact bounce. Eller har du fiksat det? Om det bara är ett cykel hjul så kan du nöjas med en delay() da det går så långsomt med et cykel hjul.

"Spara" är nog bäst i EEPROM. Jag tänker på at den altid sparer i en ny plats och när den tänds skriver den altid hela indholdet til Serial.

(Och där är stav- och andra fel i mit svensk sänn jag bor i Danmark)

Uppfinnarwannabee

ok. sorry!

Problemet är att jag är helt nollställd på
programeringen. har ett sk inventorskit
men jag fattar ändå inget (trög)

finns någon väldigt pedagogisk
tutorial som tar upp det grundläggande?

Annars om någon vänlig själ här kan hjälpa
mig med hur jag kan programmerna
mätaren?


3dprinter

Jeg har en lång yrkeserfarig i mjukvara, så jeg vet inte mere hur svårt det är att börja.  :~ På den andra sidan bruker jag vara bra at forklara. Tutorials? (f.eks. http://arduino.cc/en/Tutorial/Debounce)

Har du lykkats at ladda et program på Arduinoen? Kan du f.eks. ladda Arduinoen med Examples-Basics-Blink? Deräfter ändra i delay parameteren så den blinkar snabbare, långsammara och/eller korta blink med långt mellanrum?

olof_n

#4
Dec 29, 2013, 08:05 pm Last Edit: Dec 29, 2013, 08:32 pm by olof_n Reason: 1
Hej!

Själva "räknandet" är ganska enkelt.
För att räkna pulser kan du använda en interrupt: http://playground.arduino.cc/Code/Interrupts
Läs på om "debouncing" som Msquare skriver ovan (går att lösa med både hårdvara och mjukvara).

Sedan kan du t.ex. ha två olika knappar för att styra din räknare:
Knapp1  start/stop (startar och stoppar interrupten  samt nollställer räknaren vid start)
Knapp2 spara resultatet

Kan vara praktiskt att ha en led som indikerar ifall räknaren är på/av.

Det som gör ditt projekt lite komplicerat är att du vill kunna föra över resultatet till Excel.
Saknar man programmerings erfarenhet är det rätt besvärligt.
Det finns flera olika lösningar på det problemet:
- Spara resultatet på ett SD-kort som du läser in i datorn (http://arduino.cc/en/Reference/SD)
- Spara undan resultatet i EEPROM (http://arduino.cc/en/Reference/EEPROM)  och för över till datorn seriellt/via bluetooth eller WIFI.

Du kan ju alltid börja med räknaren och visa resultatet på en LCD-skärm.
Sedan när du lärt dig mer utökar du projektet genom att lägga till "Excel delen".

Mvh

Olof


olof_n

#5
Dec 29, 2013, 08:24 pm Last Edit: Dec 29, 2013, 08:32 pm by olof_n Reason: 1
Just det, du ville ha ett exempel.
Programmet är mycket enkelt men borde ge dig en start.
Koppla en knapp till pinne 3. Pulsen du vill räkna ska kopplas till pinne 2.

Tryck på knappen för att starta/stoppa räknaren. Resultatet skrivs ut på den seriella konsolen.

Code: [Select]


//Ange antal millisekunder som ska ignoreras (enkel debouncing)
#define minCounterTime 50
//knappast troligt att man startar/stoppar räknaren mer än 5ggr i sekunden
#define minButtonTime 200

#define knapp1 3

//Räknaren
unsigned int iCounter=0;

unsigned long ulLastDebounceTime=0;
unsigned long ulButtonDebounceTimer=0;
unsigned long ulNow=0;

byte bState=0;

void setup() {
 Serial.begin(9600);
 pinMode(2,INPUT);
 digitalWrite(2, HIGH); // slår på det interna pullup motståndet ifall externt saknas
 pinMode(knapp1,INPUT);
 digitalWrite(knapp1, HIGH); // slår på det interna pullup motståndet ifall externt saknas

}

void loop() {
 ulNow=millis();

 if ((digitalRead(knapp1)==HIGH) && (ulNow - ulButtonDebounceTimer > minButtonTime))
 {
  //Knappen är tryckt
  //Om räknaren är avstängd starta den
   if (bState==0)
    {
      Serial.println("Startar räknaren");
      iCounter=0;
      //Anropa CounterFunction ifall det kommer en puls
      attachInterrupt(2, CounterFunction, RISING);      
      bState=1;
    }
    //Annars stoppa den;
    else
    {
       detachInterrupt(2);  
       Serial.println("Stoppar räknaren");      
       Serial.println("Resultat: ");  
       Serial.println(iCounter);  
       Serial.println("");
    }
    ulButtonDebounceTimer=ulNow;
 }
}

void CounterFunction()
{
 //Om minimitiden har gått
 //Räkna upp räknare
 if ((millis() - ulLastDebounceTime) > minCounterTime)
 {
   iCounter++;
   ulLastDebounceTime=millis();
 }
}

3dprinter

Inte interrupts, snälla du. Interrupts har många överraskninger och kan vare mycket besvärliga och behövs bara om vi er i 10us området med at räkna. Et cykel hjul är i 1000-10ms området. Mycket tid at läsa pinnen på vanligt vis. (ja kanske det är lätt nog just nu, men ... men .... )

interna pullup motståndet är bäst. Knappen skal koppla pinnen till Ground/0v når den trycks, och det betyder at LOW är TILL och HIGH är FRÅN. Så blir kretsloppet helt enkelt.
Code: [Select]
pinMode(2,INPUT_PULLUP);är enklare än två linjer med pinmode og digitalwrite

Uppfinnarwannabee

Hej igen och tack för alla tips.
Jag har gjort detta program nu. Nu räknar
den antalet klick på "reed" men problemet
är att jag måste hålla in "pushbutton" och sen klicka igen på reed
då skriver den ut ett extra klick. så ex 15 klick blir 16 på serialscreen.

dvs så här. tex 16 "klick" på reed
trycker ner och håller nere "pushbutton"
klickar igen på "reed"

då skriver den ut 17 på serial.
sedan trycker jag på resetknappen på själva uno-kortet
och kan då mäta igen. och upprepa proceduren.

jag får då ut värdena snyggt som jag tänkt mig  så här på serialcreen:
15
12
12
23
osv..

förutom att alla värden är 1 för högt.
Jag tänkte försöka kopiera och klistra in från serialscreen och
kanske kan man dra av 1 från alla värden där? Men det känns som en ful
lösning och kan bli bökigt med många värden. kan jag möjligen dra bort 1
bara i koden nånstans eller?

Jag vill helst att den räcknar "reed" klicken. sen vid ett klick på "pushbutton"
skriver ut de rätta antalet "klick" och sen nollställer räknaren för en ny mätserie.
några tips hur jag kan ändra koden för att få till detta?
(Jag bifogar koden i eget inlägg)

Uppfinnarwannabee

Code: [Select]


const int  reedPin = 2;    // the pin that the reed-relay is attached to
const int buttonPin = 4;   // the pin that the push-button is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables
int reedCounter = 0;   // counter for the number of reed switches
int reedState = 0;         // current state of the reed-relay
int lastReedState = 0;     // previous state of the reed-relay
int pushButtonState;
void setup() {
  // initialize the reed pin as a input:
  pinMode(reedPin, INPUT);
  // initialize the button pin as a input
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
 
 
  // read the reed input pin:
  reedState = digitalRead(reedPin);
  // compare the reedState to its previous state
  if (reedState != lastReedState) {
    // if the state has changed, increment the counter
    if (reedState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
     
        reedCounter++;
      pushButtonState = digitalRead(buttonPin);
  if (pushButtonState == HIGH)

Serial.println(reedCounter);
    }
   
  }
  // save the current state as the last state,
  //for next time through the loop
  lastReedState = reedState;


  // turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (reedCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
   digitalWrite(ledPin, LOW);
  }

}


Uppfinnarwannabee

Jag vill förtydliga att jag kommer använda magnet och ett reed-relä på mäthjulet.
det kommer inte gå jättefort i hastighet.
Förövrigt tycker jag att det var kul att klura på det här
och att jag kom fram en liten bit även om jag inte riktigt vt vad jag gör :)
tack för all hjälp!

olof_n

Bra att du testar dig fram!

INPUT_PULLUP - Var nytt för mig, det fanns inte i tidigare versioner av IDE:et när jag började med "Arduino" (kom visst i 1.0.1)

Vet inte om jag håller med om att interrupter är speciellt komplicerat.
Att räkna pulser i en loop skulle jag aldrig bygga in mig i.
Så fort programmet börja göra mer saker än räkna  långsamma pulser (samtidigt) finns det stor risk att man missa pulser.

Naturligtvis är det aldrig fel att testa både sätten, man märker (kanske?) när den ena lösningen slutar att fungera.

Uppfinnarwannabee

Angående att skriva spara data till ett SDkort.
kan jag koppla ett SD-shield till UNO?
Finns det något sätt att få en tids/Datumstämpel
för varje mätvärde?

olof_n

#12
Dec 30, 2013, 12:58 pm Last Edit: Dec 30, 2013, 01:04 pm by olof_n Reason: 1
Hej!

Ja det går bra att koppla en en SD-shield till en UNO.

Tänk på att olika "shields" har olika fördelar.
Dom billigaste för typ 1$ tål inte 5V signaler utan behöver konverteras till 3,3V. Här är en tråd som gör det enkelt med några motstånd: http://forum.arduino.cc/index.php/topic,8863.0.html
Exempel på enkel sd-korts modul: http://www.ebay.com/itm/SD-Card-Module-Slot-Socket-Reader-for-MP3-Arduino-ARM-MCU-Read-and-Write-/161184807087?pt=AU_Gadgets&hash=item25875cf8af
Finns flera sätt att konvertera signaler mellan 5V->3,3V, vissa köper färdiga moduler eller använder speciella kretsar typ 74HC4050.

Här är en "shield" som har inbyggd konvertering: http://www.ebay.com/itm/SD-Card-Arduino-Shield-for-Arduino-UNO-R3-arduino-Mega-2560-/200975197435?pt=LH_DefaultDomain_0&hash=item2ecb0e24fb
Bara att använda utan att behöva konvertera något.

Här är en ännu bättre med både inbyggd konvertering samt klocka: http://www.ebay.com/itm/New-Data-Module-Logging-Shield-Data-Recorder-Shield-for-Arduino-UNO-SD-Card-/360804209853?pt=AU_Gadgets&hash=item54019b54bd

För det underlättar att ha en klocka (RTC) som kan ge dig tidstämplar.
Tex kanske du vill skapa upp en textfil med dagens datum eller varför inte skriva ut datum+tid först på varje loggad rad.

Ännu ett alternativ är att köpa en billig 1$ modul + en 2$ klockmodul (http://www.ebay.com/itm/I2C-RTC-DS1307-AT24C32-Real-Time-Clock-Module-for-Arduino-Uno-AVR-ARM-PIC-HP-/130962277743?pt=AU_B_I_Electrical_Test_Equipment&hash=item1e7df5c56f) - klockmodulen innehåller även ett EEPROM minne som du kan nyttja ).

Klockchipen brukar vara DS1307, DS1302 eller DS3231 (lite bättre än dom andra två).
Dom är enkla att använda även utan färdiga bibliotek (finns flera stycken bibliotek om man snabbt vill komma igång).

Go Up