Arduino - wat kun je er mee?

Voor alle vragen, reparatieverslagen en upgrades
User avatar
Peter_P
Upcoming E21 fanatic
Posts: 155
Joined: Tue Apr 15, 2014 10:57 pm

Re: Arduino - wat kun je er mee?

Post by Peter_P »

Zo aan het geluid van het motortje te horen maakt dat toch al meer dan "een paar" omwentelingen. Het zou me verbazen als er nog ernstige afwijkingen zitten in de berekening van Rob.

Verder was het te verwachten dat een kabel een hoop extra koppel zou vragen.

Goed bezig. :thumbsup


Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

Vorige week heb ik een test gedaan met een stappenmotor. Het stroom- en spanningsverloop was interessant:

rpm A kmh V
300 19,4 28 11,35
350 16,6 30 11,43
400 14,4 35 11,52
450 13,3 40 11,67
500 13,3 40 11,8
525 12,7 45 12,06
530 12,5 46 12,13
550 12,8 50 12,16


Maar ik had nog niet uitgevonden hoe je een stappenmotor accelereert dus toen ik naar de 600 toeren wilde, heb ik de driver opgefikt.

Dat heeft me wel weer aan het denken gezet. Ik zat op het spoor van een E30-snelheidsmeter maar dat had ik geparkeerd omdat ik niet begreep hoe ik met IC's de frequentie kon veranderen. Maar nu ik wel heb geleerd met de Arduino hoe het een en ander kan, en ik niet zoveel zin meer had in drivers en dat soort dingen, heb ik de E30-teller weer tevoorschijn gehaald.

Ik had wat last van gekke storingen, maar na een tijdje landde het kwartje: Mijn acculader, die ik als voeding gebruikte, is ook modulerend, dat zorgde voor heel erg gekke resultaten op de meter. Maar nu met een echte gelijkstroombron kan ik zonder problemen de E30-teller besturen. Geen elektromechanisch gedoe meer en vooral geen risico dat de boel affikt.

Nu dus de Hall-sensor onder de auto monteren en de Arduino gaat nu niet veel anders doen dan de frequentie van de puls van de Hall-sensor veranderen.
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Leuk he, zo zie je hoe het één tot het ander kan leiden.
Maar definitief op de goede weg nu.

Sluit je de hall sensor aan op D2? Dan kun je met een interrupt werken, ideaal om zo de pulstijd te bepalen en aan de hand daarvan een blokgolf met de juiste frequentie uit te sturen op een andere poort

Ben benieuwd naar je scetch.
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

Ik zat in eerste instantie aan zoiets te denken:

Looptime definieer ik als 500ms of iets dergelijks.

Code: Select all

while ((millis() - starttime) <= looptime) // Measure the RPM for a certain amount of time
  {
    sensorState = digitalRead(sensorPin);      // Read the status on input pin:

    if (sensorState != lastSensorState) {      //Is not equal to
      if (sensorState == HIGH) {
        RPM++;
      }
      lastSensorState = sensorState;


    }
  }                    //End of RPM measurement block



Om dan elke 500ms de snelheidsmeter bij te sturen door middel van iets dergelijks:

digitalWrite(OUTPUT, HIGH);
delayMicroseconds(pulse);
digitalWrite(OUTPUT, LOW);
delayMicroseconds(pulse);
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Ik heb inmiddels best veel ervaring met het meten van de actuele snelheid. Het wordt in m'n display gebruikt dat aan de megasquirt hangt, en nog belangrijker, in mijn tripmeter die we gebruiken tijdens de rally's.

Met elke puls van de hall sensor een interrupt starten is echt de gemakkelijkste manier om de tijd tussen twee pulsen te bepalen. Deze tijd bepaald dan je snelheid.

Omdat de tijden tussen de pulsen nog kunnen verschillen door bijvoorbeeld een triggerwiel met niet exact gelijke tanden, bepaal ik de gemiddelse tijd van de laatste 10 pulsen.

Dan heb je nog één ding, en dat is stil staan. In mijn toepassing is de snelheid pas 0 als er 2 sec geen pulsen ontvangen zijn.

Uiteindelijk kun je dan met de pulstijd een omgerekende blokgolf aansturen.
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Hieronder heb ik wat stukken code uit mijn tripmaster gecopieerd, welke je misschien op weg kunnen helpen.

variabelen definieren, ik laat alleen zien wat nodig is voor dit voorbeeld. daarnaast wordt de library " SimpleTimer" toegevoegd:

Code: Select all

#include <SimpleTimer.h>
SimpleTimer timer;                    // timer to do display writings e.d.
int timerID;                          // variable to store the timer ID
volatile bool puls = false;           // true after eacht received puls
volatile bool halted = true;          // to check if still receiving pulses
volatile unsigned long pulseT;        // stores micros() at each puls
unsigned long prevT,deltaT;           // for speed calculation
int PulseVal = 813;                        // distance unit (pulses per 100 meter travel) 
in de setup koppel je een routine aan interrupt 0, interrupt 0 is ingang D2, de interrupt rourtine wordt aangeroepen op de neergaande flank van de puls van de sensor (bij jou hall sensor, bij mij een proximity sensor)
Ook wordt een 200mS timer geinitialiseerd:

Code: Select all

  
void setup() {
//setup interrupt on D2 (speedpulse input)
  attachInterrupt(0, speedpulse, FALLING);
 // Setup the 200mS timer
  timerID = timer.setInterval(200, timerAction);
}
in de interrupt routine wordt de actuele tijd in microseconden opgeslagen in de variabele pulseT, daarnaast wordt de bool 'puls' geset.

Code: Select all

// do interrupt D2 stuff, speedpulse received +++++++++++++++++++++++++++++++++++++++++++
void speedpulse(){
  pulseT = micros();              // save time interupted
  puls = true;                        // set puls
}

in de loop routine wordt continu gecontroleerd of er een nieuwe "speedpulse" binnen is gekomen, zo ja, dan wordt de tijd tussen de vorige puls en de huidige puls uitgerekend, de gemiddelde pulstijd bijgewerkt, en de huidige tijd opgeslagen. daarnaast een paar bools gereset.
Ook wordt een timer aangetikt (dit is nodig om de timer goed te laten werken). deze timer loopt elke 200mS en doet in mijn geval al het overige werk.
de gemiddelde pulstijd staat in de variabele "deltaT", deze wordt dan weer in de 200mS timer routine gebruikt om de actuele snelheid weer te geven op de display.

Code: Select all

void loop() { 
    if (puls){
  // speed pulse received
  deltaT = runningAverage(pulseT-prevT);   // calc time between pulses (take average of last 10)
  prevT = pulseT;                          // save 'time' for next round
  puls = false;                              // clear puls
  halted = false;                          // bool to check if minimal 1 pulse received in next round
  }
  // tick the timer
  timer.run();
}
met deze routine wordt een gemiddelde pulstijd berekend van de laatste 10 gemeten tijden berekend.

Code: Select all

// function calculating running average out of last 10 elements ++++++++++++++++++++++++++++++++++++++
// making this higher gives faulty speed calculations at higher speeds ( if X elements * deltaT >160mS)
long runningAverage(long M)
{
  static long LM[10];      // LastMeasurements
  static byte index = 0;
  static long sum = 0;
  // keep sum updated to improve speed.
  sum -= LM[index];
  LM[index] = M;
  sum += LM[index];
  index = (index + 1) % 10;
  return sum / 10;
}

in onderstaande routine , die elke 200mS herhaald wordt, wordt de actuele snelheid berekend en naar een "printspeed" routine gestuurd, de variabele "PulseVal" bevat de omrekenwaarde, het aantal pulsen per 100 meter.

Code: Select all

// a function to be executed every 200mS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void timerAction() {
     // now calculate actual speed
    if (halted){                                                  // check is still received minimal 1 pulse in 200mS
      calcSpeed = 0; 
     }
     else{
       calcSpeed = ((360000000/PulseVal)/deltaT); 
     }
    printSpeed(calcSpeed);
    halted = true;
   }
Misschien heb je er wat aan, misschien ook niet.

-------------------------------------------------------------------

mijn tripmaster, op arduino gebaseerd:

Image
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

Goeie tip!


Even snel dan wordt het zoiets:

Code: Select all

looptime = 500
boutencardan = 6
secfactor = (1000/looptime)
eenofandererekenfactor = xx

void setup(){
attachInterrupt(digitalPinToInterrupt(2), cardan, FALLING)
}

void loop(){
if ((millis() - starttime) >= looptime){
detachInterrupt(digitalPinToInterrupt(2))
RPM = secfactor * (1/boutencardan) * 60 * pulsen
blokgolf = RPM * eenofandererekenfactor

pulsen = 0
starttime = millis()
attachInterrupt(digitalPinToInterrupt(2), cardan, FALLING)
}
}


void cardan(){
pulsen ++
}
Dan moet ik alleen nog een plekje voor deze vinden:

digitalWrite(OUTPUT, HIGH);
delayMicroseconds(blokgolf);
digitalWrite(OUTPUT, LOW);
delayMicroseconds(blokgolf);





Haha, ik was al aan het schrijven. Ik ga dat nu eerst eens even lezen. Leuk om niet alleen maar met schokbrekers en roest bezig te zijn en iemand gevonden die hebben die dat ook vind!
Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

Ik kwam er niet uit met het voortschrijdend gemiddelde en met de interrupt. Het is toch nog een stapje te hoog voor mij om dit te beheersen merk ik.

Maar ik geloof dat dit toch redelijk eenvoudige code is die ook nog lijkt te werken. Ik neem te tijd voor 6 bouten om te passeren en op die manier demp ik onregelmatigheden. Hoop ik. In plaats van een vierkante golf knippert nu het ledje op de PCB. Die factor wordt uiteraard nog anders.

Code: Select all

////////// Pin definition
int OUT_PIN = LED_BUILTIN ;
int IN_PIN = 7 ;


////////// Define all constants
int bolts = 6;                              // The number of bolts to count
unsigned long factor = 6;                   // The factor to multiply one rotation of the driveshaft with to create the square wave
int treshold = 3000;                        // Define a treshold for the stop timer to end the squarewave

////////// Define all starting values
byte in_was = LOW;                          // Concept: Look for transitions; need state memory
byte in_now;                                // Read once per cycle
int squareState = LOW;                      // Variable for the square wave
int Tround = 0;                             // The time for the drive shaft to go round once
int count = 0;                              // A counter to count the six bolts of the driveshaft
int start = 0;                              // A timer to time the time to count six bolts
int ticker = 0;                             // A ticker needed to only start the wave again after being stopped after a whole rotation of the driveshaft
unsigned long freq = 1000;                  // The frequency of the square wave
unsigned long stoptimer = millis();         // A timer to stop the wave if it takes too long
unsigned long previousmillis = 0;           // For the square wave (BlinkWithoutDelay)
unsigned long currentmillis = millis();     // For the square wave (BlinkWithoutDelay)

void setup() {
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, INPUT);
  Serial.begin(9600);
}

void loop()
{
  in_now = digitalRead(IN_PIN);              // Read the current state of the input

  if (in_was == HIGH) {                      // Were we high or low?
    if (in_now == LOW) {                     // If this statement is true, we have transitioned from high to low
      in_was = LOW;                          // Set the was-state to the current state
      count ++;                              // Start counting for six bolts to pass
      stoptimer = millis()  ;                // Start a stop timer to end the cycle if it takes too long

    //  Serial.print(count);          //Print result
        if (count == 1) {                    // When the first bolt in a rotation passes, start a clock to time 6 bolts to pass
          start = millis();
      }
    }
  }

  else {                                     // If the previous state was not HIGH, ie LOW, and it if it is HIGH by now, we have again a change
    if (in_now == HIGH) {                    // So, has transitioned from low to high
      in_was = HIGH;                         // Set the state to the new current state
    }
  }

  if (count == bolts) {                      // If we have counted the number of bolts count, there has been one rotation of the driveshaft
    count = 0;                               // Reset the counter
    Tround = (millis() - start);             // Calculate the time that took the driveshaft to turn one rotation
    ticker = 1;                              // Ticker is high after one rotation
  }

 
  unsigned long currentmillis = millis();    // Update the timer for the BlinkWithoutDelay
  freq = Tround / factor;                    // This is the equation to fix the frequency to put out

if ((millis() - stoptimer) < treshold && ticker != 0) {     // If the stop timer does not need to stop, proceed

  if (currentmillis - previousmillis >= freq) { // If the difference is larger than the frequence, it is time to change this
    previousmillis = currentmillis;          //Save the last time the square wave changed

    if (squareState == LOW) {                // If the wave is low, turn it to high and vice-versa
      squareState = HIGH;
    } else {
      squareState = LOW;
    }
    digitalWrite(OUT_PIN, squareState);      // set the wave with the squareState of the variable:
  }

}
else {
  digitalWrite(OUT_PIN, LOW);               // If there is no signal for the amount of the treshold, go to low
  ticker = 0;                               // The ticker is reset
  }
}
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Is het niet slimmer de 4 bouten van de cardanas te tellen? Die draait 4keer sneller rond, en zo zit je sensor ook nog eens beter beachermd.

Zo doet de sensor bij mij het al ruim 12 jaar prima.
Die is er toen onder gekomen vooe een signaal voor de cruise control.

Ik heb toen het aantal pulsen door 2 moeten delen voor een juist snelheid signaal voor de cruise, gewoon met een flip-flopje gedaan.
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Wilmo wrote:Ik kwam er niet uit met het voortschrijdend gemiddelde en met de interrupt. Het is toch nog een stapje te hoog voor mij om dit te beheersen merk ik.

Maar ik geloof dat dit toch redelijk eenvoudige code is die ook nog lijkt te werken. Ik neem te tijd voor 6 bouten om te passeren en op die manier demp ik onregelmatigheden. Hoop ik. In plaats van een vierkante golf knippert nu het ledje op de PCB. Die factor wordt uiteraard nog anders.

Code: Select all

////////// Pin definition
int OUT_PIN = LED_BUILTIN ;
int IN_PIN = 7 ;


////////// Define all constants
int bolts = 6;                              // The number of bolts to count
unsigned long factor = 6;                   // The factor to multiply one rotation of the driveshaft with to create the square wave
int treshold = 3000;                        // Define a treshold for the stop timer to end the squarewave

////////// Define all starting values
byte in_was = LOW;                          // Concept: Look for transitions; need state memory
byte in_now;                                // Read once per cycle
int squareState = LOW;                      // Variable for the square wave
int Tround = 0;                             // The time for the drive shaft to go round once
int count = 0;                              // A counter to count the six bolts of the driveshaft
int start = 0;                              // A timer to time the time to count six bolts
int ticker = 0;                             // A ticker needed to only start the wave again after being stopped after a whole rotation of the driveshaft
unsigned long freq = 1000;                  // The frequency of the square wave
unsigned long stoptimer = millis();         // A timer to stop the wave if it takes too long
unsigned long previousmillis = 0;           // For the square wave (BlinkWithoutDelay)
unsigned long currentmillis = millis();     // For the square wave (BlinkWithoutDelay)

void setup() {
  pinMode(OUT_PIN, OUTPUT);
  pinMode(IN_PIN, INPUT);
  Serial.begin(9600);
}

void loop()
{
  in_now = digitalRead(IN_PIN);              // Read the current state of the input

  if (in_was == HIGH) {                      // Were we high or low?
    if (in_now == LOW) {                     // If this statement is true, we have transitioned from high to low
      in_was = LOW;                          // Set the was-state to the current state
      count ++;                              // Start counting for six bolts to pass
      stoptimer = millis()  ;                // Start a stop timer to end the cycle if it takes too long

    //  Serial.print(count);          //Print result
        if (count == 1) {                    // When the first bolt in a rotation passes, start a clock to time 6 bolts to pass
          start = millis();
      }
    }
  }

  else {                                     // If the previous state was not HIGH, ie LOW, and it if it is HIGH by now, we have again a change
    if (in_now == HIGH) {                    // So, has transitioned from low to high
      in_was = HIGH;                         // Set the state to the new current state
    }
  }

  if (count == bolts) {                      // If we have counted the number of bolts count, there has been one rotation of the driveshaft
    count = 0;                               // Reset the counter
    Tround = (millis() - start);             // Calculate the time that took the driveshaft to turn one rotation
    ticker = 1;                              // Ticker is high after one rotation
  }

 
  unsigned long currentmillis = millis();    // Update the timer for the BlinkWithoutDelay
  freq = Tround / factor;                    // This is the equation to fix the frequency to put out

if ((millis() - stoptimer) < treshold && ticker != 0) {     // If the stop timer does not need to stop, proceed

  if (currentmillis - previousmillis >= freq) { // If the difference is larger than the frequence, it is time to change this
    previousmillis = currentmillis;          //Save the last time the square wave changed

    if (squareState == LOW) {                // If the wave is low, turn it to high and vice-versa
      squareState = HIGH;
    } else {
      squareState = LOW;
    }
    digitalWrite(OUT_PIN, squareState);      // set the wave with the squareState of the variable:
  }

}
else {
  digitalWrite(OUT_PIN, LOW);               // If there is no signal for the amount of the treshold, go to low
  ticker = 0;                               // The ticker is reset
  }
}
Jan Willem, ik heb je sketch even in een arduino geladen, en ondanks het vele aantal regels werkt je sketch verrassend simpel, en dat geeft helemaal niks als het microcontrollertje toch niks anders hoeft te doen. :thumbsup
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

We zullen zien wanneer ik aan de limiet kom :D


Het is nog helemaal niet nodig, maar wel leuk eens met een schermpje te klooien. Deze heeft maar twee in/uitgangen nodig en stroom, dus dat is fijn.

Image
User avatar
BertjeConti
E21 Mad
Posts: 3012
Joined: Mon Nov 04, 2013 9:49 pm
My E21(s): E12 520-6
Location: nederland , Weert

Re: Arduino - wat kun je er mee?

Post by BertjeConti »

Volgens mij heb je de smaak te pakken
Image
Megasquirted '77 E12 520-6

Aspen Silver '96 E39 523i
User avatar
uwbuurman
E21 VIP
E21 VIP
Posts: 18662
Joined: Fri Jun 12, 2009 4:49 pm
My E21(s): 1978 type 1 323i 5speed dogleg Polaris
Location: Ljouwert

Re: Arduino - wat kun je er mee?

Post by uwbuurman »

Haha, mooi man!!!
It's the man next door!

1978 BMW 323i
1980 BMW 528i maior restitutio
1987 BMW 325iA cabriolet
2006 BMW 320d touring High Executive
2015 BMW 320dA touring xDrive High Executive ///Msport
User avatar
Jeroen
Site Admin
Posts: 29246
Joined: Tue Sep 14, 2004 12:23 pm
My E21(s): '81 323i Baur
Location: The Netherlands
Contact:

Re: Arduino - wat kun je er mee?

Post by Jeroen »

Heee lachen, met uw welnemen ga ik die ook even misbruiken hahaha!
Regards/groeten, Jeroen
Wilmo
E21 Mad
Posts: 1924
Joined: Thu Jun 30, 2011 8:35 pm

Re: Arduino - wat kun je er mee?

Post by Wilmo »

Wat? De foto, de module of wat bedoel je met 'die'? ;)
Post Reply