Friday, August 12, 2022

The code

// this code was adapted from Drew Dibble original code to run on arduino due
//you´ll need a library called "soft_uart.h" ,elapsedmillis.h ,liquidcrystal.h ,and bignumbers.h installed ,search the web for it.
// this code uses the arduino due to talk to the main board Hoverboard using a 3.2v hall thumb throtlle
//instead of the gyro board.
// odometer version is from Angel Garcia de la Cruz and bignumber lcd from Sean Auffinger
// version 1.0 by Alvaro Fogassa on 23/05/2022
// !!! CAUTION !!! , do not attempt to load the sketch to arduino with the hoverboard turned on or it might damage your pc.
// the usb is not isolated and will burn your pc. make a guess how i´ve found that out. 

///// 9bit serial ///////////////////////////////////////

 #include "soft_uart.h" 
 using namespace soft_uart; 
 using namespace soft_uart::arduino_due;
 #define RX_PIN 10 // software serial port's reception pin azul 
 #define TX_PIN 11 // software serial port's transmision pin verde 
 #define SOFT_UART_BIT_RATE 26315
 #define RX_BUF_LENGTH 256 // software serial port's reception buffer length
 #define TX_BUF_LENGTH 256 // software serial port's transmision buffer length 
 uint32_t counter1=256;
 uint32_t counter2=1;
 uint32_t counter3=85;
 uint32_t counter4=0xFF;
 int sensorValue = 0; // value read from the pot
 int outputValue = 0; // value output to the PWM (analog out)
 const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
 // declaration of software serial port object serial_tc4
 // which uses timer/counter channel TC4
 serial_tc4_declaration(RX_BUF_LENGTH,TX_BUF_LENGTH);
 //serial_tc1_declaration(RX_BUF_LENGTH,TX_BUF_LENGTH); 
 auto& serial_obj=serial_tc4; //
// serial_tc4_t& serial_obj=serial_tc4;
 
 //////////////// lcd update every 100ms //////////////////////////////////////////////
#include <elapsedMillis.h>

elapsedMillis timeElapsed; //declare global if you don't want it reset every time loop runs
 unsigned int interval = 100;
 
 ///////////////// lcd bignumbers ////////////////////////////////////////////// 
#include <LiquidCrystal.h>
#include <BigNumbers.h>
 const int lcdD7Pin = 52; // LCD D7 pin 14 
 const int lcdD6Pin = 50; // LCD D6 pin 13 
 const int lcdD5Pin = 48; // LCD D5 pin 12 
 const int lcdD4Pin = 46; // LCD D4 pin 11 
 const int lcdEPin = 44; // LCD E Pin 6 
 const int lcdRSPin = 42; // LCD RS pin 4
 LiquidCrystal lcd(lcdRSPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin); //  construct LCD object
 BigNumbers bigNum(&lcd); //construct BigNumbers object, passing to it the name of our LCD object 
 // Circumference of bicycle wheel in meters.
 float bicycleWheelCircumference = 2.104867;
 const int revolutionButton = 2; 
 boolean lastRevolutionButton = LOW;
 boolean currentRevolutionButton = LOW; 
 unsigned long lastRevolutionStartTime = 0; 
 unsigned long revolutionTime = 0; // This must be the biggest display mode number
 const int currentDisplayMode = 3;
 float currentDistanceK;
 int currentMaximumKPH; 
 int currentAverageKPH; 
 int currentKPH;
 float currentDistanceM; 
 int currentMaximumMPH; 
 int currentAverageMPH; 
 int currentMPH;
 unsigned long revolutionCount = 0;
 unsigned long currentTime = 0; 
 unsigned long currentMovingTime = 0; 
 unsigned long lastStoppedTime = 0;
 unsigned long stoppedTime = 0; 
 boolean tooSlow = LOW; 
 float stoped=0.00; // added to display zero when stoped
 float km = 0.00;
 float kph = 0.00; 
 int intHours;
 int intMinutes; 
 int intSeconds;
 long previousMillis = 0; // will store last time Lcd was updated 
 unsigned long milliSecondsInSecond = 1000;
 unsigned long milliSecondsInMinute = 60000;
 unsigned long milliSecondsInHour = 3600000;
 
 void setup()
 {
  // serial_obj initialization 
  serial_obj.begin(
    RX_PIN,
    TX_PIN,
    SOFT_UART_BIT_RATE,
    soft_uart::data_bit_codes::NINE_BITS,
    soft_uart::parity_codes::NO_PARITY,
    soft_uart::stop_bit_codes::ONE_STOP_BIT
    );
    
  pinMode(revolutionButton, INPUT_PULLUP); // Sets the hall switch to be an input 
  lcd.begin(16,2); // setup LCD rows and columns
  bigNum.begin(); // set up BigNumbers
  lcd.clear(); // clear display 
  }
  int sp=0;
  void loop()
  {
    //////////////////motor controll /////////////////////////////////////////
    //we measure 50 times adn make the mean average the acelerator hall sensor value
    long measure = 0; 
    for(int i = 0; i < 50; i++){
      int value = measure += analogRead(analogInPin);
      } 
      measure /= 50;
      // read the analog in mean value and map it to outputvalue: 
      outputValue = map(measure, 477, 630, -1500, 0); // maps the throttle to the output values,need to be calibrated.
      sp=outputValue; // makes the motor to turn only forward. 
      if (sp>=1)
      { sp=0; } 
       serial_obj.write(counter1)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS)); 
        serial_obj.write(sp&counter4)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS)); 
        serial_obj.write((sp >> 8) & counter4)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS));
        serial_obj.write( sp & counter4)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS)); 
       serial_obj.write((sp >> 8) & counter4)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS)); 
        serial_obj.write(counter3)%(1<<static_cast<int>(soft_uart::data_bit_codes::NINE_BITS));
        delayMicroseconds(200); 
        
        //////////////// odometro //////////////////////////////////////////
        // Get current millis 
        currentTime = millis();
        if (tooSlow == HIGH) { 
          if ((currentTime - lastStoppedTime) >= 1000)
          {
            stoppedTime = stoppedTime + 1000; 
            lastStoppedTime = currentTime;
            }
            }
            // read Hall sensor
           currentRevolutionButton = debounce(lastRevolutionButton, revolutionButton);
            //currentRevolutionButton = (lastRevolutionButton, revolutionButton);
            if (lastRevolutionButton == HIGH && currentRevolutionButton == LOW) 
            { // Increase wheel revolution count
              revolutionCount++;
              // Compute millis it took for this latest revolution 
              if (lastRevolutionStartTime > 0) 
              { 
                revolutionTime = currentTime - lastRevolutionStartTime;
                kph = (3600000 / revolutionTime) * bicycleWheelCircumference / 1000;//
                currentKPH = kph; 
               // currentMPH = currentKPH * 0.62137119;  
                if (currentMaximumKPH < currentKPH) // If current speed is new maximum speed for this lap then store it
                { 
                  currentMaximumKPH = currentKPH; 
                  //currentMaximumMPH = currentMaximumKPH * 0.62137119;
                  }
                  
                  } 
                  lastRevolutionStartTime = currentTime;
                  }
                  lastRevolutionButton = currentRevolutionButton; 
                  // Determine if wheel revolution has taken too long. If so, cyclist has stopped display "--" instead of current speed. 
                  if ((currentTime - lastRevolutionStartTime) >= 5000) 
                  { tooSlow = HIGH; }
                  
                  if ((currentTime - lastRevolutionStartTime) < 5000)
                  { tooSlow = LOW;}
                  
                  if (revolutionCount > 0) { // Calculate current distance
                    currentDistanceK = revolutionCount * (bicycleWheelCircumference / 1000); 
                    // currentDistanceM = currentDistanceK * 0.62137119;
                    currentMovingTime = currentTime - stoppedTime;
                    
                    // Calculate average speed
                    currentAverageKPH = currentDistanceK * 3600000 / currentMovingTime;//em millis 
                    
                   // currentAverageMPH = currentAverageKPH * 0.62137119;
                   }
                   
                    // Display information on LCD
                    if (timeElapsed > interval)
                    { 
                      
                       lcd.setCursor(8,0); 
                      lcd.print(currentDistanceK);
                      lcd.print(" km");
                      
                      if (tooSlow == LOW)
                      { 
                       
                        bigNum.displayLargeInt(currentKPH , 0, 2, false);
                      }
                      else if (tooSlow == HIGH){
                          bigNum.displayLargeInt(stoped, 0, 2, false);
                      }


                // Display Average KPH in bottom right
                            lcd.setCursor(8, 1);
                            lcd.print("avg"); 
                            lcd.setCursor(12, 1); 
                            if (currentAverageKPH < 10)
                            {
                              lcd.print(" ");
                            }
                           
                            lcd.print(currentAverageKPH);
                            
                            timeElapsed = 0; // reset the counter to 0 so the counting starts over.
                            
                                } 
                            }
                            /////////////// loop end //////////////////////////// 
                            
                            //A debouncing function that can be used for any button
                            boolean debounce(boolean last, int pin) {
                              boolean current = digitalRead(pin);
                              if (last != current) 
                              { delay(1); 
                              current = digitalRead(pin);
                              } 
                              return current; 
                              }
       

No comments:

Post a Comment

The code

// this code was adapted from Drew Dibble original code to run on arduino due //you´ll need a library called "soft_uart.h" ,elap...