Go Down

Topic: THUN sensor uitlezen voor een elektrische fiets (Read 3518 times) previous topic - next topic

Hoi mensen ik ben nieuw hier, en ik hoop dat jullie me op weg kunnen helpen

Ik heb een motorcontroller die de een analoge ingang heeft van 0...5 volt, 0 volt is uit 5 volt is maximaal vermogen.

en ik heb een trapas sensor die 8 pulsen geeft van 5 volt per 360 graden draaien
ook geeft deze sensor een analoog signaal van 0.5-4.5 volt met een off-set van 2.5 volt, en dit is de krachtmeting, die alleen in het linkerpedaal zit.

deze sensor wil ik nu gaan gebruiken om de 0-5 volt te maken om zodoende "gas" te geven met mijn benen ipv een gashandel op het stuur

de sensor is een thun x-cell rt
http://www.ncte.com/download/Datasheet_X_CELL_EN.pdf

motor controller is een kelly controller
http://kellycontroller.com/mot/downloads/KellyKBSUserManual.pdf

nu heb ik de arduino uno gekocht om dit voor elkaar te krijgen, maar ik heb nog nooit geprogrammeerd.

wie kan mij op weg helpen?

MAS3

#1
Jan 26, 2013, 02:57 pm Last Edit: Jan 26, 2013, 09:26 pm by MAS3 Reason: 1
Hoi tritium21, en welkom.

Op deze site ligt de nadruk op leren.
Het gaat er dan om dat je met je nieuwe aanwinst (de uno) gaat oefenen en zo het programmeren, maar ook het gebruik van elektronica modules onder de knie krijgt.
Oefenen kun je ook lezen als spelen.
Je hebt een leuk idee om uit te werken, en een mooie sensor om dat mee te doen.

Waar je wel rekening mee moet houden is dat de sensor twee kanten op kan meten.
Je zegt namelijk dat je een sensor hebt die van 0.5 tot 4.5 kan meten, met een offset van 2.5.
Die 2.5 is dus precies in het midden, en dat is je nulpunt.
Dan meet je dus hoe hard er op de sensor gedrukt word, maar ook hoe hard "er aan getrokken" word.
Geen probleem, kun je allemaal rekening mee houden en ook gebruiken.
Want dan kun je met 1 pedaal zowel "gas geven"als remmen.
Maar dan moet je wel een pedaal hebben waar je je voet in zet, en niet alleen er op (want dan word remmen lastig).
De sensor heeft een resolutie van 10 millivolt per Newtonmeter, dus je kunt hier mooi mee rekenen.
Want dan heb je 200 stappen positief en 200 stappen negatief.
Dat past makkelijk in de range van de Arduino met 1024 stappen totaal, tussen voedingsspanning en 0 volt.
Je kunt de "map" functie gebruiken om de uitslag van je analoge ingang (dus in het programma, de hardware moet je anders doen als je dat wil aanpassen) netjes te laten passen in het bereik van je sensor.

De sensor geeft ook geen 8 pulsen per rotatie zoals je zegt, maar heeft 2 uitgangen die elk 16 pulsen per rotatie geven, en welke onderling in fase zijn verschoven.
Dat zijn voor deze 2 signalen 4 mogelijke standen (te weten respectievelijk 00, 01, 11 en 10) maal 16 per omwenteling is dus 64 signalen, een heel stuk beter dan 8 per omwenteling.
Door deze faseverschuiving kun je niet alleen zien hoe hard er getrapt word, maar ook in welke richting.
Dit soort sensoren staan ook bekend als encoders (trefwoord encoder dus).
Voor de Arduino zijn er kant en klare oplossingen om hier mee om te gaan.

Een belangrijk ander ding is de voedingsspanning van je sensor.
Minimale spanning is namelijk 7 volt en maximaal 16 volt.
Met 12 volt kom je dus een eind, maar de meeste schakelingen zoals de Arduino werken met 5 volt of minder.
Geen probleem, maar wel rekening mee houden.

Advies dat ik je verder graag geef (deze geef ik eigenlijk altijd), is om je opgave op te breken in kleine deel opgaven.
Daarmee houd je het overzichtelijk omdat je eerst de deelopgaven kunt oplossen om deze vervolgens te combineren tot een totaal oplossing.
Je houd het dan overzichtelijk voor jezelf en de kans dat je in de stress raakt door het plaatje in z'n geheel is veel kleiner.

Ik zou zeggen zoek de trefwoorden op (ook waar ik ze niet specifiek benoemd heb), en kijk of je daar hier op de site of waar dan ook meer over te weten kunt komen.
Bij voorkeur in de voorbeeld sketches die je hebt meegekregen met de Arduino IDE die je natuurlijk allang hebt gedownload hier en hebt geïnstalleerd.
Als je daar dan niet uit komt of gewoon vragen hebt, stel ze gerust.

Veel plezier met de Arduino en je project, en houd ons op de hoogte (wij leren ook van jouw vragen en opmerkingen).

[edit]Aantal toestanden per omwenteling voor de encoder toegevoegd[/edit]
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

Stealth0113

Watch my stealth-bot @ let's make robots

MAS3

Hmm.

Ik heb zojuist nog eens in de datasheet gekeken.
Daarin staat vermeld dat er 16 impulsen er omwenteling op blauw en / of bruin zijn.
Maar in tabel 2 staan er maar 8 getekend, wat inhoudt dat er 16 levels of veranderingen per omwenteling zijn, niet 16 impulsen.
Dat is dus een fout in die datasheet, en van mij om m niet eerst helemaal te lezen.
Maakt in totaal dus 32 stappen.
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

het vervelende is dat de krachtsensor alleen links zit, en dus een halve sinus vormt (trapas links boven t/m links onder) het is een race fiets dus met versnellingen, dus het negatieve gedeelte wordt niet gebruikt.

het enige wat ik nu wil is 2.5volt = 0volt en 4,5volt is 5volt,

als ik dit voor elkaar krijg ben ik al een heel eind, maar voor het mooie zou dan ook de laatste meting van links, gecopieerd moeten worden naar rechts (de andere 180 graden), dat is dan geen meting, maar anders krijg je een heel raar fietsgedrag.

atbrandt

Hoi,

Ik heb hetzelde idee opgevat en al wat code gemaakt. Het werkt, ik heb er mee gefietst! Echter er kan nog wel wat aan verbeterd worden. Grootste uitdaging waar ik tegenaan loop is het ordenen van de kabelspagetti :-).

Alex

Code: [Select]

/*
* THUN
* Reads the X-Cell RT and drives a controller based on sensed torque.
*
 
* Created 28 January 2013
* By Alexander Brandt
*
*/

// INPUT PULSE
int pulsePin = 21;       // PulseOne from crank connected to pin 31
volatile int pulse = 0;  // Hall sensor state
volatile int tempPulse = 2;

// INPUT TORQUE
int torquePin = 7;       // Analog IN pin that reads torque
volatile int torque = 0;          // Gemeten torque 0-1023
volatile int torqueMax = 0;       // Maximum torque measured last 16 pulse changes, which equals one complete circle
//volatile int torqueMaxAge = 0;    // Number if pulses that have passed since maxTorque
int torqueLowerLimit = 512;       // Inclusive 512: 2,5 volt
int torqueUpperLimit = 600;       // 919 to use full scale; 4,5 volt. Lower to increase sensitivity. Too low value will result in power falling away at peak.
volatile int torqueArray[16];
volatile int torqueArrayIndex = 0;


// OUTPUT LED
int ledPin =  13;    // LED connected to digital pin 52
int led = 1;        // LED STATE

// OUTPUT DRIVE
int drivePin = 8;    // PWM pin that drives the controller
volatile int drive = 0;       // Waarde die aan de controller wordt doorgegeven 0-255
int driveLowerLimit = 50;
int driveUpperLimit = 216;

// TIME & COUNTER VARIABLES
volatile int triggerCount = 0;
volatile int changeCounter = 0;
volatile long timeExpired = 0;
int loopDelay = 200;
volatile long lastUpdateTime = 0;   // in miliseconds from starting the program. note: will need to deal with overflow.
int timeOut = 410;
volatile int pulseCounter = 0;
volatile int timeOutCounter = 0;
volatile int updateReason = 0;

void setup() {               
  // PULSE
  pinMode(pulsePin, INPUT);
//  digitalWrite( pulsePin, HIGH);
  attachInterrupt(2, callUpdate, CHANGE);
 
  pinMode(torquePin, INPUT);     // TORQUE
  pinMode(ledPin, OUTPUT);       // LED
  pinMode(drivePin, OUTPUT);     // DRIVE
 
  // Open serial communications and wait for port to open:
  Serial.begin(57600);
  Serial.println("Hello Dave..");
 
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()

  //Serial.println("LOOP");
  timeExpired = millis() - lastUpdateTime;
  if(timeExpired > timeOut)
  {
   
    updateReason = 0;
    timeOutCounter++;
    update();
    //printDebug();
  }
//  printDebug();
  delay(loopDelay);
}                 

void callUpdate()
{
  updateReason = 1;
  pulseCounter++;
  update();
  //printDebug();
}

void update() { 
  pulse = digitalRead(pulsePin);
  digitalWrite(ledPin, pulse);
  updateTorqueMax();
  setDrive();
  lastUpdateTime = millis();
  printDebug();
}

void updateTorqueMax(){
  if(timeExpired > timeOut)
  {
    for (int i=0; i<16;i++)
    {
      torqueArray[i]=0; 
    }
    torqueMax=(1023-analogRead(torquePin));
  }
  else
  {
    torqueArray[torqueArrayIndex]=(1023-analogRead(torquePin));
    torqueMax=getTorqueMaxFromTorqueArray();
    if(torqueArrayIndex==15)
    {
      torqueArrayIndex=0;
    }
    else
    {
    torqueArrayIndex++;
    }
  }
}
   
int getTorqueMaxFromTorqueArray(){
  int max=0;
  for (int i=0; i<16;i++){
    if(max<torqueArray[i]){
      max = torqueArray[i];
    }
  }
  return max;
}

void setDrive(){
  if(torqueMax<torqueLowerLimit)
  {
    drive = driveLowerLimit-1;
//    Serial.println("WARNING: Recorded torque is lower than expected!!");
//    Serial
  }
  else if(torqueMax>torqueUpperLimit)
  {
    drive = driveLowerLimit-1;
//    Serial.println("WARNING: Recorded torque is higher than expected!!");
  }
  else
  {
     drive = map(torqueMax, torqueLowerLimit, torqueUpperLimit, driveLowerLimit, driveUpperLimit);
  }
  analogWrite(drivePin, drive);
}

void printDebug(){
/*
  Serial.print("\r                                              \r");
  Serial.print("PULSE:");
  Serial.print(pulse);
  Serial.print(" R:");
  Serial.print(updateReason);
*/
// Serial.print(timeExpired);

  Serial.print(" T:");
  Serial.print(timeOutCounter);
  Serial.print(" P:");
  Serial.print(pulseCounter);
 
/*
//  Serial.print(" TRIGG:");
//  Serial.print(triggerCount);
//  Serial.print(" DELTA:");
//  Serial.print(changeCounter);
//  Serial.print(" TRT:");
//  Serial.print(1023-analogRead(torquePin));
  Serial.print(" I:");
  Serial.print(torqueArrayIndex);
  Serial.print(" TIND:");
  Serial.print(torqueArray[torqueArrayIndex]);
  Serial.print(" TMAX:");
  Serial.print(torqueMax);
  //Serial.print(" TIME:");
  //Serial.print(timeExpired);
*/
  Serial.print(" DRV:");
  Serial.println(drive);
//  Serial.println(".");
}



#7
Feb 09, 2013, 04:19 pm Last Edit: Feb 09, 2013, 05:34 pm by tritium21 Reason: 1
mooi programma atbrandt, zou je mischien een beetje kunnen uitleggen hoe het werkt?

ik kom er kwa programeren niet uit, en heb dus zelf een printje gemaakt die de torque meting omzet van 2,5...4,5 naar 0...5 volt, elektronica snap ik beter,

dit werkt goed, en kan afgevlakt worden met een condensatortje om de tijd te overbruggen van de rechter crank, (180 graden die je mist in de meting)

mischien is het wat om dit te combineren met de puls die er uit komt op de arduino om "pedel assist" te kunnen verwezenlijken

Go Up