;********************************************************************************* ; gpspeed-demo-datalog GpSpeed simple GpSpeedDataLog demo program ; Terry@RotaryRacer, 2015-11-28 ;********************************************************************************* ; ; This is a basic test/demo example for the GpSpeedDataLog add on board. ; It uses the pixaxe download/debug serial port to communicate with the user ; so the user must enable the terminal debug window in the Picaxe programming ; software to use this program. Note on a picaxe-28X2 the baud rate will be 9600 ; ; It first waits for 4 seconds for an to be pressed. If this happens ; the system will enter command mode allowing the user to type commands. Otherwise ; the system goes into run mode logging the data. ; It then sets up the real time clock to a fixed date and time. ; It then measures and stores some data to the data log, once per second. ; ; The command mode can be extended to support, for example, setting the RTC. ; ; ; Note, when the picaxe serial cable is used as a serial debug port for inputing typed data ; from the user as it is in this program, then the picaxe cannot be programmed once the program ; has started. To program it in this case: Start the programming and then press the ; GpSpeed reset button. There is a small window of opportunity when the picaxe starts up were ; it can be programmed in this case. ; ; Uses fixed point scaled variables in 16bit integers for some things. These are scaled by 100. ; So 12.34 Volts is stored as 1234. ; ; For: PICAXE-28X2 (PIC18F25K22) ; ; GpSpeed pins are: ; B.1 LED ; C.2 Motor PWM ; C.1 Fan PWM ; A.0 Analogue Input 0, I0, throttle ; A.1 Analogue Input 1, I1, misc ; A.2 Analogue Input 2, Voltage measurement ; A.3 Analogue Input 3, Current measurement (Hall effect) ; B.4 Analogue/Digital Input, I2 ; ; B.2 Analogue Input 8, Current measurement (Mosfet) ; B.0 Error, error from Motor PWM ; C.3 I2C Clk ; C.4 I2c Dat ; C.0 User 0, I2c Int ; B.3 User 1 ; C.6 SER1 TX ; C.7 SER1 RX ; ; PWM range at 20kHz: 0 - 400 ; ; Compile time options ; Uncomment to use Hall effect throttle ;#define UseHallThrottle ; Uncomment to set the date/time to fixed values ;#define DoSetTime ; Symbols for pin names symbol pinLed = B.1 ; The LED pin symbol pinPwmMotor = C.2 ; The motors PWM pin symbol pinPwmFan = C.1 ; The fans PWM pin ; Symbols to allocate variables. Variables w0-w7 (b0 - b15) are used as temporary variables symbol year = b16 ; The year symbol month = b17 ; The month symbol day = b18 ; The day symbol hour = b19 ; The hour symbol minute = b20 ; The minute symbol second = b21 ; The second symbol throttle = w11 ; The throttle input value 0 - 1000 symbol throttle.lsb = b22 symbol throttle.msb = b23 symbol voltage = w12 ; The battery voltage scaled by 100 symbol voltage.lsb = b24 symbol voltage.msb = b25 symbol current = w13 ; The battery currents scaled by 100 symbol current.msb = b26 symbol current.lsb = b27 symbol speed = w14 ; The battery currents scaled by 100 symbol temperature = b30 ; The temperature reading symbol spare1 = b31 ; The temperature reading symbol logPos = w16 ; The current datalog write position symbol pos = w17 ; Position symbol tmp = w18 ; General purpose temporary value symbol loopCount = b38 ; Loop count ; Symbols for CPU's internal EEPROM symbol eepromLogPos = 0 ; The current position in the dataLog init: ; setfreq m4 let adcsetup = %000000000001111 ; Initialises ADC inputs gosub logInit ; Setup the data log gosub rtcInit ; Initialise the real time clock loopCount = 0 start: gosub commandCheck ; Check if any user commands #ifdef DoSetTime ; Setup the date/time to a fixed starting value sertxd ("Set RTC's date and time", 13, 10) year = 15 month = 12 day = 1 hour = 10 minute = 0 second = 0 gosub rtcWrite #endif mainLoop: ; The main processing loop. Once per second sertxd ("Main loop", 13, 10) gosub rtcRead ; Read the date and time readadc10 0,throttle ; Reads the ADC throttle input #ifdef UseHallThrottle if throttle < 210 then ; Limit to Hall Effect's 1 - 4V range throttle = 210 endif if throttle > 810 then throttle = 810 endif throttle = throttle - 210 ; Offset to 0 throttle = throttle * 10 / 6 ; Scale to 0 - 1000 #else if throttle < 15 then throttle = 0 endif if throttle > 1000 then throttle = 1000 endif #endif readadc10 2,voltage ; Reads the ADC voltage input voltage = voltage * 10 / 3 ; Scales the voltage so 100 = 1V readadc10 3,current ; Reads the ADC current input if current > 514 then ; 0 Amps is 512 and current increases with lower values current = 514 endif current = 514 - current ; Offset current to half way (Sensor provides +- current) if current < 0 then current = 0; endif current = current * 119 / 6 ; Invert and scale current so 1Amp = 100 readadc10 A.1,temperature ; Reads the ADC temperature input ; temperature = temperature * 24 ; Scale to degreesC for TMP37 temperature = temperature * 49 ; Scale to degreesC for TMP36 ; Add to the datalog gosub logAppend ; sertxd ("LogAppended: ", #logPos, 13, 10) sertxd ("LogAppended: ", #logPos, ": ", #year, "-", #month, "-", #day, " ", #hour, ":", #minute, ":", #second, 13, 10) ; Every second processing loopCount = loopCount + 1 toggle pinLed ; Flash the LED ; Main loop delay pause 1000 ; 1000ms delay goto mainLoop ; Command input commandCheck: ; Waits for 4 seconds for any user response. If any enters command mode sertxd ("Type to go into command mode", 13, 10) serrxd [4000], b0 if b0 = 13 then sertxd ("GpSpeed Commands", 13, 10) sertxd (" q - Quit to run mode", 13, 10) sertxd (" d - Download data log", 13, 10) sertxd (" r - Reset data log to start", 13, 10) sertxd (" t - Set the date and time", 13, 10) do ; Command loop sertxd ("cmd> ") serrxd b0 sertxd (b0, 13, 10) if b0 = "d" then gosub commandDownloadLog elseif b0 = "r" then gosub logReset elseif b0 = "t" then gosub timeSet endif loop while b0 != "q" endif reconnect return commandDownloadLog: ; Downloads the data log to the serial debug lines sertxd ("GpSpeed data log", 13, 10) sertxd (#logPos, 13, 10) if logPos = 0 then return endif w2 = logpos - 1 for pos = 0 to w2 w0 = pos gosub logGet tmp = 2000 + year; sertxd (#tmp, "-", #month, "-", #day, "T", #hour, ":", #minute, ":", #second) sertxd (" ", #voltage, " ", #current, " ", #throttle, " ", #speed) sertxd (13,10) next sertxd ("end", 13,10) return timeSet: ; Sets the RTC time sertxd ("Send datetime (year month day hour minute second)", 13, 10); serrxd #year, #month, #day, #hour, #minute, #second gosub rtcWrite sertxd ("Set to: ", #year, "-", #month, "-", #day, "T", #hour, ":", #minute, ":", #second, 13, 10) return ;****************************************************************************** ; RTC Subroutines ;****************************************************************************** ; ; Provides functions to read and write the date and time from the RTC. ; Note the RTC uses BCD (binary coded decimal) for its data rather than plain binary integers ; rtcInit: ; Initialises the RTC with a set date/time hi2csetup i2cmaster, $D0, i2cslow, i2cbyte return rtcSetTime: ; Hard coded date/time in BCD: sec, min, hour, wday, day, month, year, control: 15/12/01 12:00:00 hi2csetup i2cmaster, $D0, i2cslow, i2cbyte hi2cout 0, ($00, $00, $12, $01, $01, $12, $15, $00) return rtcRead: ; Reads the current date/time as integers into year,month,day,hour,minute,second hi2csetup i2cmaster, $D0, i2cslow, i2cbyte hi2cin 0, (b2, b3, b4) ; read sec, min, hour hi2cin 4, (b5, b6, b7) ; read day, month, year ; Convert BCD values to integers b1 = b2 & $0F ; Get the units second = b2 / 16 * 10 + b1 ; Get tens and add units b1 = b3 & $0F ; Get the units minute = b3 / 16 * 10 + b1 ; Get tens and add units b1 = b4 & $0F ; Get the units hour = b4 / 16 * 10 + b1 ; Get tens and add units b1 = b5 & $0F ; Get the units day = b5 / 16 * 10 + b1 ; Get tens and add units b1 = b6 & $0F ; Get the units month = b6 / 16 * 10 + b1 ; Get tens and add units b1 = b7 & $0F ; Get the units year = b7 / 16 * 10 + b1 ; Get tens and add units return rtcWrite: ; Writes the current date/time as integers from year,month,day,hour,minute,second to the RTC b1 = second // 10 ; Convert second to BCD b2 = second / 10 * 16 + b1 b1 = minute // 10 ; Convert minute to BCD b3 = minute / 10 * 16 + b1 b1 = hour // 10 ; Convert hour to BCD b4 = hour / 10 * 16 + b1 b1 = day // 10 ; Convert day to BCD b5 = day / 10 * 16 + b1 b1 = month // 10 ; Convert month to BCD b6 = month / 10 * 16 + b1 b1 = year // 10 ; Convert year to BCD b7 = year / 10 * 16 + b1 hi2csetup i2cmaster, $D0, i2cslow, i2cbyte hi2cout 0, (b2, b3, b4) ; write sec, min, hour hi2cout 4, (b5, b6, b7) ; write day, month, year return bcdToNum: b1 = b0 & $0F ; Get the units b0 = b0 / 16 * 10 + b1 ; Get tens and add units return rtcTest: ; Simple test loop reading the date and time and outputing it to the serial debug lines gosub rtcRead sertxd (#day, "/", #month, "/", #year, " ", #hour, ":", #minute, ":", #second, 13, 10) pause 1000 goto rtcTest ;****************************************************************************** ; Log Subroutines ;****************************************************************************** ; ; The data logs write position is stored in the CPU's internal EEPROM area as a ; 16 bit pointer to a complete 16 byte data record. ; Note that the CPU's internal EEPROM is reset to 0 when a new program is downloaded ; logInit: ; Initialise I2C bus, access to I2C EEPROM chips and read old logPos hi2csetup i2cmaster,$A0, i2cslow, i2cword read eepromLogPos, b0, b1 logPos = b1 << 8 | b0 return logReset: ; Reset data logging position to the start, 0 logPos = 0 b0 = logPos & $FF b1 = logPos >> 8 write eepromLogPos, b0, b1 return logAppend: ; Append a data log entry and increment the log position b0 = logPos >> 11 & $FE + $A0 w1 = logPos << 4 hi2csetup i2cmaster, b0, i2cslow, i2cword hi2cout w1, (year, month, day, hour, minute, second, throttle.lsb, throttle.msb, voltage.lsb, voltage.msb, current.lsb, current.msb) pause 5 ; It takes up to 5ms for the EEPROM chip to write the data logPos = logPos + 1 b0 = logPos & $FF b1 = logPos >> 8 write eepromLogPos, b0, b1 return logGet: ; Fetch a log entry from the location given in w0 b2 = w0 >> 11 & $FE + $A0 w0 = w0 << 4 hi2csetup i2cmaster, b2, i2cslow, i2cword hi2cin w0, (year, month, day, hour, minute, second, throttle.lsb, throttle.msb, voltage.lsb, voltage.msb, current.lsb, current.msb) return