Arduino Koppel & Vermogen

Arduino specifieke Software
Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Arduino Koppel & Vermogen

Berichtdoor Gij Kieken » 28 Feb 2016, 20:49

Arduino koppel & vermogen.

Ik heb een stukje code geschreven en geladen in een Arduino UNO R3.
De code werkt goed echter zo nu en dan valt de seriëel communicatie uit, dit kan zowel na 1 min.

als na pakweg een 5 tal zelfs 10 tal minuten.
De code op zich is zeer minimalistisch dit om de Arduino niet te lang bezig te houden met

berekeningen.
Ik gebruik VB6 om de data op de USB lijn te loggen, om vervolgens de nodige berekeningen uit te

voeren en op te slaan in een xxx.csv file voor een grafiekje te teken in Excel.
De data is een integer die iedere 250ms de waarde van de acceleratie ( aantal pulsjes van een

encoder schijf 60 gaatjes per toer max. 3000rpm) van een aandrijfas met vliegwiel (totaal pakweg

120kg) aangeeft.
De doelstelling is het koppel en vermogen van een gokart te kunnen loggen en uitprinten bij

wijzigingen aan de motor of overbrenging.
De vraag is waarom valt de serieel verbinding nu en dan een keer uit.
Heb al wat met de baud rate geëxperimenteerd maar niet echt een oplossing.
Ook ligt het niet aan de VB6 code, want het gebeurt ook als ik enkel de serieel monitor van de

Arduino IDE laat lopen. (nu aan de waarden van de monitor heb ik niet veel maar het was als test).
Misschien is het de TimerOne library van de Arduino.CC site die in overflow gaat.
Maar dit is nog een brug te ver voor mij om een library volledig uit te pluizen en te begrijpen op

eigen houtje.
Een Run of test van een gokart duurt ongeveer 10sec ( van 0->100km/h +-3 sec) dit even ter zijde.
Wat belangrijk is ,is de acceleratie.


Code: Alles selecteren

#include <TimerOne.h>
  volatile int rev=0;
 void isr() //interrupt service routine
{
rev++;
}
void plot()
{
  detachInterrupt(0);           // detaches the interrupt 
  Serial.println(rev);
  rev=0;
  attachInterrupt(0,isr,CHANGE);
  }
void setup()
{
  Serial.begin(9600);
  attachInterrupt(0,isr,CHANGE);  // attaching the interrupt
  Timer1.initialize(250000);      // sample time 250ms
  Timer1.attachInterrupt(plot); // attach the service routine here
}
void loop()
{
}
 

Advertisement

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Arduino Koppel & Vermogen

Berichtdoor nicoverduin » 28 Feb 2016, 21:37

Ik zou zeker geen Serial activiteiten in een interrupt routine gooien. En je gaat midden in een interrupt een nieuwe interrupt verbinden.
Ik zou die code ff anders maken.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Arduino Koppel & Vermogen

Berichtdoor Gij Kieken » 28 Feb 2016, 21:56

Die void plot eruit gooien dan en iets in de loop plaatsen?
Ik had ook wat naar de priority van de interrupts zitten kijken,vandaar deze code

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Arduino Koppel & Vermogen

Berichtdoor nicoverduin » 28 Feb 2016, 22:47

wat wil je eigenlijk precies bereiken?
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Arduino Koppel & Vermogen

Berichtdoor Gij Kieken » 28 Feb 2016, 23:02

Mijn bedoeling was om de code zo kort en krachtig als mogelijk te maken.
Had al geprobeerd om meer sampels per seconde te verkrijgen maar dan werd de absolute(relatieve)fout te groot.Dit om de acceleratie beter in kaart te brengen.
Bij mijn eerste probeersels schreef ik naar een SD card om het zaakje te loggen, probleem werd dan de schrijftijd naar de SD card en ook het geklungel met het SD cardje in uit de shield voor in de Pvc te steken.
Had een en ander getest met generator scoop en frequentie meter, om toch ergens te kunnen calibreren.
Nu bleek 4 maal per seconde een behoorlijk meetresultaat te geven, meer zou natuurlijk beter zijn.
De code die ik nu geschreven had werkt goed enkel dat de serieel verbinding nu en dan hapert.
Losse of slechte contactjes heb ik natuurlijk ook nagezien.
Had tevens geprobeerd met millis in de loop i.v.p. TimerOne.
Uw sugestie om het anders te schrijven ,kun je een tip van de sluier lichten?
De bedoeling is om bij te leren, het is niet de bedoeling om een en ander klakeloos over te nemen, ik wil het begrijpen ook.
De code volledig in machiene taal schrijven is voor mij ook nog een beetje te ver gegrepen.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Arduino Koppel & Vermogen

Berichtdoor nicoverduin » 29 Feb 2016, 00:53

Bij een SD kaartje blijkt dat de eerste schrijf lang duurt. Ik heb dit programma ooit schreven voor een zeepfabriekje in malawi. Kan tot ongeveer 60000 metingen per seconde op een een SD kaart schrijven. Daarna stort alles in. Mogelijk heb je er wat aan. Ik bouw 2 buffers op om weg te schrijven. Dus niet gelijk elke keer naar die SD. Eerst een array opbouwen en dan die wegschrijven. Terwijl hij wegschrijft, vul ik een andere buffer en zo om en om. Dus ahw parallel verwerking. De interrupts komen in dit geval van een lichtsluis af.
cpp code
/**
* @file Malawi_001.ino
* @author Nico Verduin
* @date 30-12-2013
*
* @mainpage Malawi_001
* This project measures time between pulses generated from a photo sensor. The time between each
* rising and falling edge is measured as well as the time between the falling and rising edge.
* The time measured in both cases is stored on an SD Card.
* \n\n
* The given estimations of the HIGH time vs LOW time is 150 milli Seconds (variation = 120-170) and
* 30 milli seconds (variation = 10-50).
*
* @par Important information
* SD cards are sold in different qualities. The most important is the so called latency time
* This can influence the delay on the write operation.
*
* @par Workings
* An interrupt service routine (ISR) is called every time the edge changes. The difference between
* the time now and the time before is the time between edges. \n
* These values are stored in an array. Each array can contain a maximum of BUFFER_ENTRIES (=max 100) bytes.\n
* The program has 2 buffers once a buffer is full, the buffer pointer is switched to the other allowing
* the ISR to keep storing data. \n
* Meanwhile the filled buffer is written to the SD card as a 2 column CSV format with a Long and short pulse time.
*
* @par Usage instructions
* a) Make sure a standard FAT32 formatted SD card is inserted in the card Holder\n
* b) Switch the Arduino on\n
* c) The LED should light constant\n
* d) recording will start as soon as pulses arrive from the Opto
*
* @par LED flashes
* a) 2 seconds on / 2 seconds off : There is no SD card inserted or card not usable\n
* b) 1 seconds on / 2 seconds off : The card already contains 99 MALAWIxx files. Either clean up the card or use another\n
* c) 250 milliseconds on / 250 milliseconds off : a buffer overrun has happened.\n
* In all cases above recording has terminated or not even started\n
* \n
* If a very short flash happens once every 3-4 seconds the data is being recorded on the card and the system is operating perfectly.
*
* @par Version Control
* $Revision: 5 $
* $Author: Nico $
* $Date: 2013-12-31 14:55:38 +0100 (di, 31 dec 2013) $
*
* @par License info
*
* Malawi_001 measuring time between pulses
*
* Copyright (C) 2013 Nico Verduin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Program : Malawi_001 Copyright (C) 2013 Nico Verduin
* This is free software, and you are welcome to redistribute it.
*
*/

#include "Arduino.h"

#include <SD.h> // SD Card functions
//
// file name specifics
//
char fileName[13]; // we will use msDos files here(8 + . + 3 +\0)
char fileType[] = ".csv"; // just plain text file
char fileNameStart[] = "MALAWI"; // files will start with MALAWI
File dataFile; // file object to write to

//#define DEBUG // DEBUG purposes
#define FIELD_SEPARATOR ";" // for CSV file
//
// Pin definitions
//
#define LED 6 // LED turns on if no buffer full
#define CS 10 // Chip select for SD card
#define INTERRUPT_INPUT 2 // digital pin for interrupt 0
//
// variables used between the ISR and the loop
//
#define BUFFER_ENTRIES 50 // currently we have 50 entries per buffer
#define FLASH_OVERRUN 150 // flash on/off every 150 milli seconds buffer overrun
#define FLASH_CARD 2000 // flash on/off every 2000 milli seconds no Card
#define FLASH_100 1000 // flash on/off every 1000 milli seconds no Card
#define NO_CARD 1 // no card inserted or unreadable
#define OVERRUN 2 // buffer overrun
#define FILE100 3 // we have reached a 100 files

volatile bool firstValue = true; // ignore the first value as we need 2 values to start with
volatile unsigned long oldValue; // contains the previous millis value
volatile unsigned long currentValue; // current millis value
volatile int buffer[2][BUFFER_ENTRIES]; // we use 2 buffer for writing (each is 512 bytes in size)
volatile int *ptrBuffer; // points to first empty address in buffer
volatile uint8_t bufferIndex; // references correct buffer
volatile unsigned int entryIndex; // keeps track of entry in buffer
volatile boolean bufferFull; // indicates if a buffer can be written to SD card
volatile unsigned int error = 0; // an error occured

/**
* @name flash(unsigned long flashTime)
* @param flashTime sets the time the LED is on and off
* flashes the Led
*/
void flash(unsigned long flashTime) {

unsigned long flashCtr;

flashCtr = millis() + flashTime; // set the timer
digitalWrite(LED, !digitalRead(LED)); // flip the LED
while (millis() < flashCtr){}; // wait until done
}
/**
* @name HandleEdgeChange()
* This is the Interrupt Service Routine called every time the pulse edge changes
*/
void HandleEdgeChange() {
//
// get the time in any case
//
currentValue = millis();
//
// check if this is the first value
//
if (firstValue) {
//
// we start with the rising edge
//
if (digitalRead(INTERRUPT_INPUT) == LOW) {
//
// this is the start
//
oldValue = currentValue; // first value will be 0
firstValue = false; // we will do this only once
}
} else {
//
// calculate the difference
//
*ptrBuffer = currentValue - oldValue; // calculate the difference and put it in the buffer
ptrBuffer++; // pointer to next integer position
//
// now increment the Entry index and check for buffer full. if not we are done
//
entryIndex++;
if (entryIndex == BUFFER_ENTRIES) {
//
// buffer is full so switch to other buffer but first check if other buffer is empty
//
if (bufferFull) {
//
// not emptied yet so set error flag
//
error = OVERRUN;
}
bufferIndex = !bufferIndex; // index can only be 0 or 1
entryIndex = 0; // reset the entry ctr
ptrBuffer = &buffer[bufferIndex][0]; // pointer to first entry in current buffer
bufferFull = true; // previous buffer can be written
}
}
//
// save the current value as old for the next interrupt
//
oldValue = currentValue;
}

/**
* @name writeBuffer(uint8_t index)
* @param index pointer to writable buffer
* Writes a buffer of integer values to the file
*/
void writeBuffer(uint8_t index) {
//
// copy the data to the file in readable format
//
#ifdef DEBUG
Serial.print("Write Buffer");
unsigned long start = millis(); // needed to determine writing time
#endif
for (unsigned int i = 0; i < BUFFER_ENTRIES; i++) {

dataFile.print(buffer[index][i]);
dataFile.print(FIELD_SEPARATOR);
i++;
dataFile.println(buffer[index][i]);
}
dataFile.flush();

#ifdef DEBUG
Serial.print("Duration = ");
Serial.println(millis() - start);
#endif
}

/**
* @name setup()
* initialize the program
*/
void setup()
{
#ifdef DEBUG
Serial.begin(9600); // for debug purposes
#endif

//
// setup inputs and outputs
//
pinMode(LED , OUTPUT); // Led will indicate if Buffer is empty
pinMode(CS , OUTPUT); // SD card select
//
// turn LED off
//
pinMode(LED, HIGH);
//
// initialize buffers and pointers
//
ptrBuffer = &buffer[0][0]; // Points to first index in first buffer
entryIndex = 0; // references first entry in buffer
bufferIndex = 0; // references the first buffer
bufferFull = false; // nothing to write yet

//
// Initialize the SD card
//
if (!SD.begin(CS)) {
#ifdef DEBUG
Serial.println("Card failed, or not present");
#endif
//
// set error code
//
error = NO_CARD;
return;
}
#ifdef DEBUG
Serial.println("card initialized.");
#endif

//
// find the first free file name to use
//
strcpy(fileName, fileNameStart);
//
// currently set for max 999 files
//
for (unsigned int i = 1; i < 99; i++) {
//
// build the number range
//
sprintf(&fileName[sizeof(fileNameStart)-1], "%02d", i);
strcat(fileName, fileType);

if (SD.exists(fileName)) {
#ifdef DEBUG
//
// just let us know the file was created earlier
//
Serial.print(fileName);
Serial.println(" Exists");
#endif
//
// No more files allowed on this card
//
if (i == 99) {
error = FILE100;
break;
}
} else {
//
// create the new file and let us know
//
dataFile = SD.open(fileName, FILE_WRITE);
#ifdef DEBUG
Serial.print(fileName);
Serial.println(" Created");
#endif
//
// we found the file so exit loop
//
i = 100;
}
}
//
// print a dummy to dataFile as the first write takes about 10x as long as normal
//
dataFile.println("Short;Long");
dataFile.flush();
//
// now attach the interrupt to the ISR so it can respond to pulses
//
attachInterrupt(0, HandleEdgeChange, CHANGE);
}

/**
* @name loop()
* main loop of program and runs endlessly
*/
void loop()
{
//
// first check if there is an error
//
if (error != 0) {
//
// remove interrupt vector, no use continuing
//
detachInterrupt(0);
//
// flash determined on error type
//
switch (error) {

case NO_CARD: // no card detected or unusable
flash(FLASH_CARD);
break;

case OVERRUN: // buffer overrun
flash(FLASH_OVERRUN);
break;

case FILE100: // we have 99 files from this sketch on the SD card
flash(FLASH_100);
break;

default:
break;
}
} else {
//
// write to the SD card only if there is something to write
//
if (bufferFull) {
//
// we have to write a buffer away
//
digitalWrite(LED, !bufferFull); // if buffers are empty, it is a false so reverse it
writeBuffer(!bufferIndex); // we have to write the other buffer as this one
// is filling
bufferFull = false;
}
//
// check if buffers are still empty
//
digitalWrite(LED, !bufferFull); // if buffers are empty, it is a false so reverse it
}
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Arduino Koppel & Vermogen

Berichtdoor shooter » 29 Feb 2016, 10:07

ik zou ook gaan voor de methode van nico, want schrijven naar de SD kaart is wel te onderbreken en een serial signaal niet.
inderdaad gaat er wat fout met de timer want die wordt ook door de serial poort gebruikt.
persoonlijk zou ik de microsecondentimer gebruiken in de ISR, die is een stuk nauwkeuriger. en nooit detachinterupt gebruiken want dan kun je pulsen verliezen. alleen de tijd opslaan bij elke puls.
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Arduino Koppel & Vermogen

Berichtdoor nicoverduin » 29 Feb 2016, 10:42

Daarnaast kan je beter gebufferd schrijven. Of je nu 2 bytes of 100 bytes in een keer wegschrijft maakt vrijwel niets uit met een SD kaart. En wat ik in het programma doe is 2 arrays maken. Je begint met het vullen van de eerste. Is deze vol dan ga je die wegschrijven. In de tussentijd vul je de andere. Is die weer vol dan vul je de andere. Met een generator erop kun ik zo rond de 60000 metingen. Daarna ging het verhaal niet meer op omdat je de ene buffer nog niet weggeschreven was terwijl de andere al vol was. En nee deze techniek is niet nieuw.... Dat paste we in feite al toe in de 70ér jaren als je een magneetband ging volschrijven met blokken (lees array) van iets meer dan 5Kbytes
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Arduino Koppel & Vermogen

Berichtdoor Gij Kieken » 29 Feb 2016, 12:06

Bedankt Nico, ik zal je code verder onder de loepe nemen,zal wel even duren voor ik het allemaal snap, maar dit is nou de uitdaging.
Bij mijn bedenkingen had ik ook al de pro en contras afgewogen inzake de meetmethode.
M.a.w. de tijdsduur meten tussen een vast aantal puslen ofwel hetgeen ik nu deed.(vandaar dat ik de code zo kort als mogelijk wilde houden)
Ook had ik een constructie opgezet met 2 arrays voor de te tellen pulsen.Want nu mis ik inderdaad een aantal pulsen als de ik void plot binnen ga.
Dit loste ik op in de VB code door een constante op te nemen (gemiste pulsen, wrijving, slip, temperatuur, etc), proef onder vindinglijk had ik deze waarde bepaalt.
En heel veel proberen en lezen ,(de kracht van de codes vind ik in de kleine voorbeeldjes zoals Blink without Delay etc...)

Heel erg bedankt, kan weer een stukje verder.

Gebruikers-avatar
Berichten: 631
Geregistreerd: 15 Nov 2015, 11:54

Re: Arduino Koppel & Vermogen

Berichtdoor Gij Kieken » 29 Feb 2016, 12:28

shooter schreef:ik zou ook gaan voor de methode van nico, want schrijven naar de SD kaart is wel te onderbreken en een serial signaal niet.
inderdaad gaat er wat fout met de timer want die wordt ook door de serial poort gebruikt.
persoonlijk zou ik de microsecondentimer gebruiken in de ISR, die is een stuk nauwkeuriger. en nooit detachinterupt gebruiken want dan kun je pulsen verliezen. alleen de tijd opslaan bij elke puls.


Hey Shooter , detachinterrupt had ik er bij geplaatst om het keurig te houden, althans dit had ik zo begrepen uit de literatuur.De eerste probeersels waren ook met een SD kaartje,had een constructie opgezet om telkens een nieuwe flie aan te maken indien deze reeds bestond en iets met twee array's om ondertussen te kunnen weg schrijven.Maar natuurlijk niet van zo een omvang ,diepgang en techniek zoals die van Niko, daarvoor ben ik nog wat te licht bevonden als je begrijp wat ik bedoel.
Door het geklungel met die Sd kaartjes, zeker de Micro SD wou ik het via USB doen.
Ben nu terug wat zoet met de code van Nico te doorgronden.

Volgende

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: ugolcekupuqod en 90 gasten