Ayudadme con un "Indicador de marchas para moto según pulsos velocidad y r.pm."
Página 1 de 1.
Ayudadme con un "Indicador de marchas para moto según pulsos velocidad y r.pm."
Pues eso el circuito lo hizo Pat Fruth en el 2007 pero para una honda y en mi yamaha FZ6 no funciona bien, bailan las marchas.
Basicamente lo que hace es cuando se genera una interrupcion por rpm empieza a contar los pulsos de la rueda. La estrella de encendido da 8 pulsos por vuelta y la rueda 30 (mas despacio )si no recuerdo mal. Lo que hace es la media de 8 capturas y luego guarda el dato como referencia para indicar la marcha que esta engranada la transmision.
Creo que si en vez de mirar la media se le diera un valor max y min para la primera , vaya un margen de valores variables para cada marcha no habria problema. Al leer el resultado que guarda en la eprom oscila pero siempre entre los mismos valores. El circuito lo he construido con kicad y con toner/plancha para hacerlo en una sola cara, que el autor lo hizo en dos.
Me podriais echar una mano? ... ya se que mi unica contribución al foro es que se abriera el apartado de presentaciones pero es que no sé mucho más.
Cuando pueda contar bien las marchas le quitaria la posibilidad de invertir los numeros que no tiene sentido y le pondria un indicador de "candado puesto en la rueda" a traves de un interruptor en su soporte y quizás un scottoiler (engrasador automatico) casero.
La verdad es que hay unos cuantos hechos con pic pero no liberan el codigo y este que es GNU me gustaria mejorarlo y publicarlo.
Basicamente lo que hace es cuando se genera una interrupcion por rpm empieza a contar los pulsos de la rueda. La estrella de encendido da 8 pulsos por vuelta y la rueda 30 (mas despacio )si no recuerdo mal. Lo que hace es la media de 8 capturas y luego guarda el dato como referencia para indicar la marcha que esta engranada la transmision.
Creo que si en vez de mirar la media se le diera un valor max y min para la primera , vaya un margen de valores variables para cada marcha no habria problema. Al leer el resultado que guarda en la eprom oscila pero siempre entre los mismos valores. El circuito lo he construido con kicad y con toner/plancha para hacerlo en una sola cara, que el autor lo hizo en dos.
Me podriais echar una mano? ... ya se que mi unica contribución al foro es que se abriera el apartado de presentaciones pero es que no sé mucho más.
Cuando pueda contar bien las marchas le quitaria la posibilidad de invertir los numeros que no tiene sentido y le pondria un indicador de "candado puesto en la rueda" a traves de un interruptor en su soporte y quizás un scottoiler (engrasador automatico) casero.
La verdad es que hay unos cuantos hechos con pic pero no liberan el codigo y este que es GNU me gustaria mejorarlo y publicarlo.
- Código:
;---------------------------------------------------------------------------------------------
;Description: Program for displaying the gear position of a Honda motorcycle
; on a seven segment LED display
; Copyright (C) 2007 Pat Fruth
;
; 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.
;
; 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/>.
;
;Version: 1.3
;Date: 12.22.2007
;MCU: PIC16F88
;Author: Pat Fruth email:pat@patfruth.com
;Change History:
; V1.3 12.22.2007
; Added ambient light sensor to automatically adjust display intensity.
; Incorporated a standard Cadmium Sulfide (CdS) photo-cell to sense ambient light conditions,
; by setting up a simple voltage divider.
; Using PORTA pin AN2 as an analog input, an A/D conversion is done to sense night time
; riding conditions. If it's dark out, then reduce the display intensity by turning off the
; transistor that normally drives the common anode leg of the seven segment display.
; Cleaned up numerous comment typos. Can you say "spell checker" ;-)
; Cleaned up formatting for easier reading.
; V1.2 12.01.2007
; Initial stable version
;---------------------------------------------------------------------------------------------
; DISCLAIMER:
; IN NO EVENT, UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SHALL I, OR ANY
; PERSON BE LIABLE FOR ANY LOSS, EXPENSE OR DAMAGE, OF ANY TYPE OR NATURE ARISING OUT OF THE
; USE OF, OR INABILITY TO USE THIS SOFTWARE OR PROGRAM, INCLUDING, BUT NOT LIMITED TO, CLAIMS,
; SUITS OR CAUSES OF ACTION INVOLVING ALLEGED INFRINGEMENT OF COPYRIGHTS, PATENTS, TRADEMARKS,
; TRADE SECRETS, OR UNFAIR COMPETITION.
;---------------------------------------------------------------------------------------------
;Overview:
; Most Honda motorcycles have no direct indication of which gear the transmission is in at
; any given moment in time. It is left to the rider to sense, and remember, which gear he/she
; is in. Most modern Hondas do, however, have an electronic fuel injection & ignition system.
; As such, there are several electrical signals that can be measured/leveraged in order to facilitate
; the derivation of the information necessary to determine which gear the transmission is in at
; any given moment in time. This information can then be directly provided to the rider via
; a visual display mechanism.
; The following four signals are monitored in order to derive the information necessary to
; determine which gear the transmission is in;
; - The counter shaft on a Honda incorporates a variable reluctance type pulse generator
; that produces a digital square wave signal. This pulse generator is often referred to as the
; "Vehicle Speed Sensor" (VSS) in the Honda service manuals. The signal's frequency varies in
; direct proportion to rear wheel speed.
; - The flywheel on a Honda engine incorporates a variable reluctance type pulse generator that
; produces a semi-square wave A/C signal. This pulse generator is often referred to as the
; "Ignition Pulse Generator" in the Honda service manuals. This signal's frequency varies in
; direct proportion to engine speed.
; - There is a mechanical SPST neutral switch, providing continuity to chassis ground when
; the transmission is in neutral.
; - There is a mechanical SPST clutch switch, providing continuity to chassis ground when the
; clutch is disengaged (in other words, when the rider has the clutch pulled in).
;
; Running this program, the microcontroller continuously monitors the four afore mentioned
; signals, and visually displays the following information on a seven segment LED display.
; Char Description
; ---- -----------
; "0" Neutral
; "1" 1st gear
; "2" 2nd gear
; "3" 3rd gear
; "4" 4th gear
; "5" 5th gear
; "6" 6th gear (for those that have six gears)
; "-" a dash, indicating the clutch is disengaged
; "L" indicates the unit is in "Learning" mode
;
; Learning mode -
; Upon initial installation and powerup, the microcontroller must first be "taught" how may
; gears the motorcycle has, and then, for each of those gears, how many ignition cycles
; occur for a defined set of counter shaft revolution cycles. These values are captured,
; and then stored in the microcontroller's on-board EEPROM memory so that it may then
; be retrieved/used in the future. This program incorporates a special "Learn" mode algorithm
; to do just that. Upon power up, the software checks to see if there is valid data stored
; in EEPROM memory. If not, "Learn" mode is entered. If so, normal execution proceeds.
; There is also logic to accommodate a momentary pushbutton, which can be used to force "Learn" mode
; to be entered. If the pushbutton is being depressed during power-on-reset, and is held
; down for approximately one second immediately there-after, "Learn" mode will be entered.
; When "Learn" mode is entered in this way, an "L" will be displayed on the LED display, at
; which point the pushbutton should then be released. Upon entering "Learn" mode, the
; display will begin to continuously flash 5 and then 6. When the number, corresponding
; to the number of gears the motorcycle has, is showing (either 5 or 6), pressing the pushbutton
; will cause that number to be stored, and then used as the number of gears in the future.
; The display will begin to quickly flash that number, as confirmation that the selection has
; been made for that number of gears. When the pushbutton is then released, the display will
; proceed to slowly flash gear number 1. With the motorcycle running, and on a center/rear
; stand, the rider should put the motorcycle in first gear, and release the clutch.
; Once the rear wheel is spinning, the rider should depress & hold the pushbutton, signaling
; the microcontroller to proceed to learn the number of ignition cycles that occur for a given
; number of counter shaft cycles. This measurement is repeated eight times. The average of those
; eight measurements is then calculated, and stored into EEPROM memory. At this point the
; display will begin to quickly flash the gear number that was just learned. The rider can
; then release the pushbutton, signaling the microcontroller to proceed with learning the next
; gear. This process is repeated until all gears have been learned.
;
; Ambient light sensor -
; The single-digit seven segment display's brightness/intensity is automatically adjusted,
; based on the intensity of the surrounding ambient light conditions. During normal mid-day
; riding conditions, the display's brightness will be high so that it can be seen in
; moderate-to-intense ambient light. During night-time riding conditions, the display's
; intensity will be low so that it won't be a blinding distraction.
; This is accomplished by configuring a simple voltage divider, comprised of a fixed value
; resistor and a cadmium sulfide photo-cell. The resulting voltage drop created by the
; cadmium sulfide photo-cell is measured by coupling the voltage divider to the PORTA RA2/AN2
; pin, which is configured as an analog A/D converter input channel.
; In order to minimize "false trigger" occurrences, and to provide a certain level of hysteresis,
; these ambient light measurements are captured in a 16 byte array. As new measurements are
; captured, the oldest measurements are overwritten. Each time a new measurement is captured,
; a new rolling average of the last 16 measurements is calculated.
; Because there is considerable variability in photo-cell performance characteristics (not to
; mention rider preferences), this program includes a feature which allows the rider to "set"
; the desired ambient light threshold at which the display's intensity should switch from
; high to low. Depressing the "Learn" pushbutton for 1 second after the motorcycle is turned
; on (running or not), and in neutral, will cause the current average ambient light level
; measurement to be captured and stored in EEPROM data memory. When the capture is complete,
; the display will begin to flash, at which point the pushbutton can be released.
; This measurement will then be used as the threshold going forward. Ambient light conditions
; lower than this threshold will result in the display's intensity being lowered.
;
; Display intensity -
; The actual adjustment of the display's intensity is accomplished by switching a transistor
; on or off. The transistor is used to bypass the current limiter in the seven segment display's
; common anode leg connection to Vdd. This provides a more direct path to Vdd, thus increasing
; current draw of the display. The base of the transistor is connected to the PORTA RA3 pin.
; Setting RA3 to logic low turns the transistor on, thereby increasing the display's intensity.
; Setting RA3 to logic high turns the transistor off, thereby decreasing the display's intensity.
;
; PORT pin assignments -
; PORTB
; RB0 = input.
; Receives the signal from the motorcycle's Vehicle Speed Sensor (VSS).
; Configured to exploit the microcontroller's external interrupt feature.
; RB1:RB7 = output
; Used to drive the individual segments of the seven segment LED display.
; PORTA
; RA0 = input.
; Receives input from the motorcycle's neutral switch circuit.
; Logic 0 (low) indicates the transmission is in neutral.
; Logic 1 (high) indicates the transmission is not in neutral.
; RA1 = input.
; Receives input from the motorcycle's clutch switch circuit.
; Logic 0 (low) indicates the clutch is engaged.
; Logic 1 (high) indicates the clutch is not engaged.
; RA2 = analog input.
; Receives input from a simple voltage divider network, incorporating a standard
; Cadmium Sulfide (CdS) photo-cell. The higher the A/D result, the darker the ambient
; light conditions. 0xFF = full dark, 0x00 = intense light.
; RA3 = output.
; Drives a PNP transistor that connects the common anode leg of the seven segment display
; to Vdd. Logic low turns the transistor on, thus allowing maximum current to flow thru
; the seven segment display LEDs. When the transistor is turned off current is forced to
; flow thru a 1K ohm current limiting resistor, thus reducing the display's intensity.
; RA4/T0CKI = input.
; Receives the signal from the motorcycle's Ignition Pulse Generator (IPG).
; Configured as the external clock source for the microcontroller's built-in Timer0 module.
; Timer0 is configured to run in asynchronous counter mode.
; RA5 = input.
; Unused. Tied low via connection to ground.
; RA6 = input.
; Receives input from the "Learn" mode momentary pushbutton switch.
; Logic 0 (low) indicates the button is being depressed.
; Logic 1 (high) indicates the button is not being depressed.
; RA7 = input.
; Receives input from the "Digit Orientation" two-pin header/jumper.
; Logic 0 (low) indicates the jumper is shorted.
; Logic 1 (high) indicates the jumper is open.
; If shorted, this indicates that the user has mounted the LED display upside down, and
; thus the output information should be presented accordingly.
;
; Data EEPROM storage map -
; Addr Description
; ---- -----------
; 0x00 Number of gears
; 0x01 Number of IGP cycles per VSS cycle for 1st gear
; 0x02 Number of IGP cycles per VSS cycle for 2nd gear
; 0x03 Number of IGP cycles per VSS cycle for 3rd gear
; 0x04 Number of IGP cycles per VSS cycle for 4th gear
; 0x05 Number of IGP cycles per VSS cycle for 5th gear
; 0x06 Number of IGP cycles per VSS cycle for 6th gear
; 0x07 Valid data signature. 0xCC indicates valid data. Anything else indicates invalid data
; 0x08 The ambient light sensor threshold
;---------------------------------------------------------------------------------------------
ERRORLEVEL -302 ;remove message about using proper bank
;***** Declarations and microcontroller configuration *****
PROCESSOR 16f88
#include "p16f88.inc"
__CONFIG _CONFIG1, _CP_OFF&_DEBUG_OFF&_WRT_PROTECT_OFF&_CPD_OFF&_LVP_OFF&_BODEN_ON&_MCLR_OFF&_PWRTE_ON&_WDT_OFF&_INTRC_IO
__CONFIG _CONFIG2, _IESO_OFF&_FCMEN_OFF
;***** Declaration of variables *****
cblock 0x20 ; Beginning of RAM in bank 0
AMBIENT0 ; The AMBIENT0-F array MUST be aligned on a 16 byte boundary
AMBIENT1 ; AMBIENT0-F hold the A/D results for the last 16 A/D conversions
AMBIENT2 ; of the ambient light sensor
AMBIENT3
AMBIENT4
AMBIENT5
AMBIENT6
AMBIENT7
AMBIENT8
AMBIENT9
AMBIENTA
AMBIENTB
AMBIENTC
AMBIENTD
AMBIENTE
AMBIENTF
AMBIENTIX ; Index to the current AMBIENT address, used for indirect addressing
AMBIENTSUML ; Low order byte of the sum of the above 16 ambient samples
AMBIENTSUMH ; High order byte of the sum of the above 16 ambient samples
AMBIENTAVG ; Average of the 16 array entries above
AMBIENTTHRESH ; The level at which the display intensity should be lowered
TEMP ; Various temporary use
VSSINTS ; Counts the interrupts that result from the VSS square wave
VSSINT ; An internal (software) interrupt prescaler, boolean 0x00=no int, 0xff=int
TMR0_1 ; Holds the first copy of the Timer0 counter
TMR0_2 ; Holds the second copy of the Timer0 counter
NUMGEARS ; The number of gears for this motorcycle
GEAR ; Holds the gear number to be displayed on the seven segment LED display
GEAR2 ; Holds the gear number, used as a count down loop counter
THRESH1 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 1st gear
THRESH2 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 2nd gear
THRESH3 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 3rd gear
THRESH4 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 4th gear
THRESH5 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 5th gear
THRESH6 ; Retrieved from EEPROM, holds the "learned" number of IPG cycles for 6th gear
PAUSEH ; Used by the Pausems routine, holds the high order byte of the number ms
PAUSEL ; Used by the Pausems routine, holds the low order byte of the number ms
LOOPCOUNT ; Used by various routines, as a loop counter
IPGSUML ; Low order bye of the sum of IPG pulses
IPGSUMH ; High order bye of the sum of IPG pulses
endc
cblock 0x70 ; Beginning of RAM memory common to all banks
W_TEMP ; Temporary storage of the W register, used by the interrupt service routine
STATUS_TEMP ; Temporary storage of the STATUS register, used by the interrupt service routine
endc
;***** Declaration of symbol equates *****
LEARNBTN equ 6 ; PORTA, pin RA6, has the "Learn" mode pushbutton
NEUTRALSW equ 0 ; PORTA, pin RA0, has the Neutral switch input
CLUTCHSW equ 1 ; PORTA, pin RA1, has the Clutch switch input
INTENSITY equ 3 ; PORTA, pin RA3, controls display intensity
;***** Beginning of program memory structure *****
ORG 0x00 ; Reset Vector
goto Init ; After power-on-reset, jump to this location
ORG 0x04 ; Interrupt vector
goto IntSvc ; Interrupt Service routine
;***** Beginning of interrupt service routine *****
; This code is executed any time an "Interrupt", of any kind, occurs.
; Here we place logic that queries the various interrupt flags in order to determine the reason
; for the interrupt.
; In this particular case, the only interrupt that should be happening is the INTF interrupt.
; Each time a low-to-high transition occurs on the RB0/INT pin, as a result of the pulses arriving
; from the VSS, we will briefly interrupt execution of the main processing loop, execute
; this little bit of code, and then return control back to the main loop.
IntSvc
; Save W & STATUS
movwf W_TEMP ; Copy W to TEMP register
swapf STATUS,W ; Swap status to be saved into W
; Swaps are used because they do not affect the status bits
movwf STATUS_TEMP ; Save status to STATUS_TEMP register
btfss INTCON,INTF ; Are we handling an INT on RB0?
goto IntSvcExit ; No
btfss INTCON,INTE ; Are we supposed to be handling INT interrupts at this time?
goto IntSvcExit ; No
; This routine tallies up counter shaft rotation cycles emitted by the VSS.
; Each time this ISR is driven, the counter shaft will have rotated a fraction of a full revolution.
; Note: On the Honda RC51, there are 27 pulses per counter shaft revolution.
; Here we effectively divide the VSS frequency by 128.
; We use a RAM variable (VSSINT) as a boolean indicator of these rotations.
; Every 64 cycles from the VSS will result in the VSSINT variable switching from 0x00 to 0xFF
; or vise versa. The state of the VSSINT variable is monitored in the main loop routine below.
incf VSSINTS,F ; Increment the VSSINTS ram variable
btfss VSSINTS,6 ; Have we tallied up 64 (0x40, B'01000000') of em yet?
goto IntSvcExit ; No
clrf VSSINTS ; Yes, so restart the counter
comf VSSINT,F ; And toggle the VSSINT flag
IntSvcExit
bcf INTCON,INTF ; Clear the Interrupt flag
; Restore W & STATUS
swapf STATUS_TEMP,W ; Swap STATUS_TEMP register into W
; (sets bank to original state)
movwf STATUS ; Move W into STATUS register
swapf W_TEMP,F ; Swap W_TEMP
swapf W_TEMP,W ; Swap W_TEMP into W
retfie ; Return from interrupt
;***** Beginning of main execution logic. Execution begins here upon power on *****
Init
; Initialize the system clock oscillator frequency
banksel OSCCON
bsf OSCCON,IRCF1 ; Configure the internal system clock to run at 4MHz
bsf OSCCON,IRCF2 ; IRCF2:IRFC1:IRFC0 = B'110'
; Initialize the Watch Dog Timer (WDT) period select for approx 1 second timeout.
; But leave the WDT disabled, we'll enable it later.
; In the case where the motorcycle stops moving, there will be no more interrupts
; arriving from the VSS. Thus, it is possible that we get stuck in an infinite loop
; in the DoIPGCount routine, waiting for the VSSINTS varible to switch states.
; The WDT is used here to break this infinite loop, and reset the processor.
; The WDT runs on it's own dedicated oscillator (31.25 kHz). So we configure the
; period select configuration bits to scale this down to give us an approx 1 sec
; timeout. 31,250 Hz / 32768 = .953 Hz = 1.04 sec.
banksel WDTCON
movlw B'00010100' ; period select = 1:32768, SWDTEN = 0 (off)
movwf WDTCON
banksel OPTION_REG
bcf OPTION_REG,PS2 ; PS2:PS0 = 000 means prescaler 1:1
bcf OPTION_REG,PS1
bcf OPTION_REG,PS0
; Initialize A/D converter channels
banksel ANSEL
movlw B'00000100' ; Make all channels digital except RA2/AN2
movwf ANSEL
; Initialize PORTB
banksel TRISB
movlw B'00000001' ; Make PORTB all output, except RB0
movwf TRISB
banksel PORTB
movlw 0xFF ; Turn off all seven segment display segments
movwf PORTB
; Initialize PORTA
banksel TRISA
movlw B'11110111' ; Make PORTA all input, except RA3
movwf TRISA
bcf PORTA,INTENSITY ; Bring RA3 low (make the display bright)
; Initialize the A/D converter so we can sense ambient light conditions.
; We effectively make it an 8-bit conversion by configuring the A/D result as left-justified.
banksel ADCON1
bcf ADCON1,VCFG0 ; Configure the A/D converter to use Vdd & Vss as +/- Vrefs
bcf ADCON1,VCFG1
bcf ADCON1,ADFM ; Configure A/D result to be left-justified
banksel ADCON0
bcf ADCON0,CHS0 ; Select A/D Channel 2 CHS=b'010'
bsf ADCON0,CHS1
bcf ADCON0,CHS2
bsf ADCON0,ADCS0 ; Use internal RC oscillator for A/D conversions
bsf ADCON0,ADCS1
bcf ADCON0,ADON ; Turn off the A/D converter, we'll turn it on when we need it.
banksel PIE1
bcf PIE1,ADIE ; Disable A/D Interrupts. We're going to poll instead
; Initialize Timer0 module as an async counter so it can count IPG cycles
banksel OPTION_REG
bsf OPTION_REG,T0CS ; Timer0 clock source is RA4/T0CKI
bcf OPTION_REG,T0SE ; Increment Timer0 on rising edge
; Initialize RAM variables
banksel 0
clrf VSSINTS ; Start VSS interrupts off at zero
clrf VSSINT ; Turn off our quasi VSS interrupt flag
bsf INTCON,INTE ; Enable RB0/INT to generate interrupts from the Vehicle Speed Sensor (VSS)
bcf INTCON,GIE ; But disable Global Interrupts for now
btfss STATUS,NOT_TO ; Check to see if a Watch Dog Timer reset occurred
goto LoadEE ; If so, then just reload data from EEPROM and go
; Use indirect addressing to clear the 16 byte array that holds
; the ambient light sensor samples.
; Only do this during normal reset. Leave this data in place
; in the case of a WDT reset.
movlw low AMBIENT0 ; Get the memory address of the beginning of the array
movwf AMBIENTIX ; Save it. It'll be used as an array index later on.
movwf FSR ; And put it in the File Select Register (FSR)
clrf INDF ; The INDF Special Function Register will act on the address contained in the FSR
incf FSR,F ; Point to the next array entry
btfss FSR,4 ; Have we done all 16 yet?
goto $-3 ; No, so do the next one
; Test to see if we should go into "Learn" mode.
; The PORTA RA6 pin has a pushbutton. Holding the button down will cause the pin to go low
btfsc PORTA,LEARNBTN ; Check if the push button is being held down
goto LoadEE ; If not, then proceed
movlw high .1000 ; If so, then setup to debounce for 1 sec (1000 ms)
movwf PAUSEH
movlw low .1000
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; And check if the button is still being held down
goto LoadEE ; If not, then proceed
; Here we begin the "Learn" mode.
; If we got here, then the user either powered up with the "Learn" mode button depressed,
; or the main routine determined that the EEPROM contents was invalid, and has to be (re)populated.
; First we must display the letter "L" on the LED display.
; Then we forcibly invalidate the contents of EEPROM.
; Valid EEPROM contents is indicated by the presence of a special value (0xCC) in EEPROM
; storage location 0x07. Writing 0xFF to this location therefore indicates invalid data.
StartLearn
movlw high Hexto7seg
movwf PCLATH
movlw 0x07 ; code for "L" (for "Learn")
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the segments in the display
movlw 0x07 ; Get ready to write data to EEPROM location 0x07
movwf GEAR
movlw 0xFF ; Write 0xFF to EEPROM
call WriteEE ; Go write the data to EEPROM
btfss PORTA,LEARNBTN ; Wait for the button to be released
goto $-1 ; Loop until button released
movlw 0x05 ; Start with 5 gears
movwf GEAR
; First we must determine the number of gears this motorcycle has.
; So, we begin by slowly flashing 5, and then 6. When the number corresponding to the number
; of gears for this motorcycle is showing, depressing the pushbutton will cause that number
; to be stored in EEPROM location 0x00. This is then used to control operations going forward.
LearnNumGears
movlw high Hexto7seg
movwf PCLATH
movfw GEAR ; Get the gear number to be displayed
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
movlw high .1000 ; Pause for 1 sec
movwf PAUSEH
movlw low .1000
movwf PAUSEL
call Pausems
btfss PORTA,LEARNBTN ; Check if button pressed?
goto StoreNumGears ; Yes, so go store the number of gears
movlw 0xFF ; Turn off the PORTB pins
movwf PORTB
movlw high .500 ; Pause for 500 ms
movwf PAUSEH
movlw low .500
movwf PAUSEL
call Pausems
incf GEAR,F ; Increment to the next gear
movfw GEAR ; Get the gear number
xorlw 0x07 ; Have we gone past 6th?
btfss STATUS,Z
goto LearnNumGears ; No
movlw 0x05 ; Yes, so wrap back to 5
movwf GEAR
goto LearnNumGears
; Now that the pushbutton has been pressed, indicating that the number of gears has been
; selected... begin quickly flashing that number as confirmation. When the button is
; released, then proceed to learn the individual gears
StoreNumGears
movfw GEAR ; Get the GEAR number into W
movwf NUMGEARS ; Save NUMGEARS for use in loop control going forward
movlw high Hexto7seg
movwf PCLATH
movfw GEAR
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; Check if button still pressed
goto LearnGears ; No, so go start learning each gear
movlw 0xFF ; Turn off all segments
movwf PORTB
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
goto StoreNumGears ; Then continue flashing the display quickly
LearnGears
movfw NUMGEARS ; Store the number of gears for this motorcycle
clrf GEAR ; Set GEAR to zero (used as the EEPROM storage addr)
call WriteEE ; Write the data
; Get ready to iterate thru the "Learn" mode
incf GEAR,F ; Start at gear number 1
movfw NUMGEARS ; And set up a count-down loop counter
movwf GEAR2
; Begin Learn mode, by flashing the gear number on/off slowly (once every second).
; We'll do this until the user depresses the pushbutton.
BlinkSlow
movlw high Hexto7seg
movwf PCLATH
movfw GEAR ; Get the GEAR number to be displayed on the LED
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
movlw high .500 ; Pause for 500 ms
movwf PAUSEH
movlw low .500
movwf PAUSEL
call Pausems
btfss PORTA,LEARNBTN ; Check if button pressed
goto Learn ; If so, proceed to learn it
movlw 0xFF ; Otherwise, turn off all segments
movwf PORTB
movlw high .500 ; Pause for 500 ms
movwf PAUSEH
movlw low .500
movwf PAUSEL
call Pausems
goto BlinkSlow ; Continue to flash the display
; Learn the actual number of IPG cycles per VSSINT transision
Learn
movlw high .100 ; Debounce the pushbutton. Pause for 100 ms
movwf PAUSEH
movlw low .100
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; Check if button is still depressed
goto BlinkSlow ; If not, then resume flashing
call AvgIPGCount ; Now go get the average of 8 sample timings
addlw 0x03 ; Add some padding
call WriteEE ; Store the timing for this gear into EEPROM
; Indicate that "Learning" has completed, by flashing the gear number on/off quickly (once every 400 ms).
; We'll do this until the user releases the pushbutton.
BlinkFast
movlw high Hexto7seg
movwf PCLATH
movfw GEAR ; Get the GEAR number to be displayed on the LED
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; Check if button pressed
goto LearnNext ; If not, proceed to set up for learning the next gear
movlw 0xFF ; Turn off all segments
movwf PORTB
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
goto BlinkFast ; Then continue flashing the display quickly
; Now that we've "Learned" a gear, and the user has released the pushbutton, set up for learning
; the next gear.
LearnNext
movlw high .100 ; Debounce the pushbutton. Pause for 100 ms
movwf PAUSEH
movlw low .100
movwf PAUSEL
call Pausems
btfss PORTA,LEARNBTN ; Check if button is still released
goto BlinkFast ; If not, then resume flashing
incf GEAR,F ; Increment the gear number to be learned
decfsz GEAR2,F ; Decrement the learning loop counter, and exit if zero
goto BlinkSlow ; Got start blinking the new gear number we need to learn
; Whewww, we're done
movlw 0x07
movwf GEAR
movlw 0xCC ; Now write the special signature (0xCC), indicating EEPROM data is valid
call WriteEE ; Write the data
; Here we retrieve all previously "Learned" data from EEPROM.
; If we got here, then the user either powered up without the "Learn" mode button depressed,
; or the "Learn" code above has just completed.
; First we check to see if the special signature (0xCC) is present at EEPROM location 0x07.
; If not, then we proceed to "Learn" mode. If so, we re-hydrate all the RAM variables that hold
; the previously learned values.
LoadEE
movlw 0x07 ; Start with the location that is supposed to hold our special signature
movwf GEAR ; 0x07 in this case
call ReadEE ; Go retrieve a byte of EEPROM data from that location
xorlw 0xCC ; Did the special signature come back?
btfss STATUS,Z ; If so, the Z (zero) bit in the STATUS register will be set
goto StartLearn ; No, so go to "Learn" mode code
decf GEAR,F ; Re-hydrate all the RAM variables used to hold the thresholds
call ReadEE ; Working from gear 6 thru 1
movwf THRESH6 ; .
decf GEAR,F ; ..
call ReadEE ; ...
movwf THRESH5 ; ....
decf GEAR,F
call ReadEE
movwf THRESH4
decf GEAR,F
call ReadEE
movwf THRESH3
decf GEAR,F
call ReadEE
movwf THRESH2
decf GEAR,F
call ReadEE
movwf THRESH1
decf GEAR,F ; Location zero will contain the number of gears for this motorcycle
call ReadEE
movwf NUMGEARS
movlw 0x08 ; EEPROM location 0x08 holds any previously learned ambient light
movwf GEAR ; light sensor threshold
call ReadEE
movwf AMBIENTTHRESH
banksel WDTCON
bsf WDTCON,SWDTEN ; Turn on the Watch Dog Timer now.
banksel 0
;---------------------------------------------------------------------------------------------
; This is the beginning of "THE" main loop.
; Once all the initialization, learning, and EEPROM data retrieval has completed, we execute
; this infinite loop.
; Each iteration of the loop does the following:
; - Checks the state of the neutral, and clutch switches.
; - If neither is active, do a timing to get the current number of IPG cycles per VSS cycles.
; - Display the results on the LED display.
; - Get an A/D conversion for the voltage level of the ambient light sensor.
; - Compute a rolling average of the 16 most recent ambient light sensor samples.
; - Adjust the intensity of the display, based on the average ambient light level.
; - Pause for 100ms.
Loop
btfss PORTA,NEUTRALSW ; Are we in neutral?
goto DebounceNeutral ; Yes
btfss PORTA,CLUTCHSW ; Is the clutch pulled in?
goto DebounceClutch ; Yes
call DoIPGCount ; Otherwise go get a current view of IPG cycles to VSS cycles
movwf TEMP ; Save the results of the count
; The following series of tests essentially zeros in on which
; gear we are currently in. It does this by comparing the
; newly stored timing to the previously learned values for each
; gear until it finds the right threshold. When we exit the
; this series of tests, the GEAR variable will have the GEAR
; number to be displayed.
movlw 0x06
movwf GEAR ; Move 6 to the gear indicator
movfw NUMGEARS
xorlw 0x06 ; Does this motorcycle have 6 gears?
btfss STATUS,Z
goto $+5 ; No, so skip around the test for 6th
movfw TEMP
subwf THRESH6,W ; If W > THRESH, then C will be clear
btfsc STATUS,C ; If C is clear, then we're in a lower gear
goto Display
decf GEAR,F ; Decrement to 5th gear
movfw TEMP
subwf THRESH5,W ; If W > THRESH, then C will be clear
btfsc STATUS,C ; If C is clear, then we're in a lower gear
goto Display
decf GEAR,F ; Decrement to 4th gear
movfw TEMP
subwf THRESH4,W ; If W > THRESH, then C will be clear
btfsc STATUS,C ; If C is clear, then we're in a lower gear
goto Display
decf GEAR,F ; Decrement to 3rd gear
movfw TEMP
subwf THRESH3,W ; If W > THRESH, then C will be clear
btfsc STATUS,C ; If C is clear, then we're in a lower gear
goto Display
decf GEAR,F ; Decrement to 2nd gear
movfw TEMP
subwf THRESH2,W ; If W > THRESH, then C will be clear
btfsc STATUS,C ; If C is clear, then we're in a lower gear
goto Display
decf GEAR,F ; so we must be in 1st gear
goto Display
DebounceNeutral
movlw .20 ; Debounce constant
movwf LOOPCOUNT ; Initialize debounce loop counter
movfw PORTA ; Make a copy of the contents of PORTA
andlw B'00000001' ; Mask off all but RA0
movwf TEMP ; Save it
DebounceNeutral1
movfw PORTA ; Check PORTA again
andlw B'00000001' ; Mask off all but RA0
xorwf TEMP,W ; Seen it before?
btfss STATUS,Z
goto DebounceNeutral ; No
decfsz LOOPCOUNT,F ; Yes, so decrement the loop counter and exit if zero
goto DebounceNeutral1 ; If loop counter still > zero, check the switch again
btfsc PORTA,NEUTRALSW ; Still indicating neutral?
goto Loop ; No
movlw 0x0 ; Display "0" on the LED display
movwf GEAR
; But first.......
; If the user is pressing the "learn" button at this point, then he wants to set the
; ambient light threshold to the current averaged ambient light conditions.
; So here, we check the state of the button. If it is being held down for a second, then
; we stash the current ambient sensor rolling average into EEPROM location 0x08, blink the
; display, and wait for the button to be released.
btfsc PORTA,LEARNBTN ; Is the learn button is being pressed?
goto Display ; No, so go display gear
banksel WDTCON ; We must turn off the Watch Dog Timer so we don't incur
bcf WDTCON,SWDTEN ; a device reset
banksel 0
movlw high .1000 ; Debounce by pausing for 1 sec
movwf PAUSEH
movlw low .1000
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; Is the learn button still being pressed?
goto AmbientLearnExit ; No, so get out
movlw 0x08 ; Yes, so set the EEPROM location to hold the ambient threshold
movwf GEAR
movfw AMBIENTAVG ; Get the most current averaged ambient light sensor level
movwf AMBIENTTHRESH ; Save it as the new threshold
xorlw 0x00 ; Are we at minimum already?
btfss STATUS,Z
decf AMBIENTTHRESH,F ; No, so bump it by 1
movfw AMBIENTTHRESH ; get it back into W
call WriteEE ; Now write it to EEPROM
AmbientLearnBlink
movlw 0x00 ; Blink code for neutral
movwf GEAR
movlw high Hexto7seg
movwf PCLATH
movfw GEAR
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
btfsc PORTA,LEARNBTN ; Check if button still pressed
goto AmbientLearnExit ; No
movlw 0xFF ; Turn off all segments
movwf PORTB
movlw high .200 ; Pause for 200 ms
movwf PAUSEH
movlw low .200
movwf PAUSEL
call Pausems
goto AmbientLearnBlink ; Then continue flashing the display quickly
AmbientLearnExit
clrwdt
banksel WDTCON
bsf WDTCON,SWDTEN ; Turn the Watch Dog Timer back on
banksel 0
goto Display
DebounceClutch
movlw .20 ; Debounce constant
movwf LOOPCOUNT ; Initialize debounce loop counter
movfw PORTA ; Make a copy of the contents of PORTA
andlw B'00000010' ; Mask off all but RA1
movwf TEMP ; Save it
DebounceClutch1
movfw PORTA ; Check PORTA again
andlw B'00000010' ; Mask off all but RA1
xorwf TEMP,W ; Seen it before?
btfss STATUS,Z
goto DebounceClutch ; No
decfsz LOOPCOUNT,F ; Yes, so dec loop counter and continue if zero
goto DebounceClutch1 ; If loop counter still > zero, check the switch again
btfsc PORTA,CLUTCHSW ; Still indicating clutch pulled in?
goto Loop ; No
movlw 0x08 ; Dummy gear number to indicate a "-" (dash)
movwf GEAR
Display
movlw high Hexto7seg
movwf PCLATH
movfw GEAR ; Get the gear number into the W register
call Hexto7seg ; Convert it to a 7 segment display decode
movwf PORTB ; Turn on the PORTB pins
call DoAmbient ; Go get a fresh sample from the ambient light sensor
call AvgAmbient ; Go compute a rolling average of the ambient samples
; Is the ambient average at, or above, the threshold?
subwf AMBIENTTHRESH,W ; The higher the number, the less intense the ambient light
btfss STATUS,C ; If not, carry will be set
goto $+3 ; No, so jump around
bcf PORTA,INTENSITY ; Bring RA3 low (makes the display bright)
goto $+2 ; Jump around
bsf PORTA,INTENSITY ; Bring RA3 high (makes the display dim)
movlw high .100 ; Pause for 100 ms
movwf PAUSEH
movlw low .100
movwf PAUSEL
call Pausems
clrwdt
goto Loop ; Jump to the beginning of the main loop, and do it all again.
; End main loop
;---------------------------------------------------------------------------------------------
; Begin subroutines
; Subroutine: Pausems
; Used to burn some CPU cycles doing nothing meaningful.
; This routine assumes a system clock frequency of 4 MHz.
; Inputs:
; PAUSEL - Low order byte of the number of milliseconds
; PAUSEH - High order byte of the number of milliseconds
; Temporary:
; LOOPCOUNT - Loop counter
; Output:
; None
Pausems
Loop1
movf PAUSEL,F ; Decrease PAUSEH and PAUSEL the necessary
btfsc STATUS,Z ; number of times and call subprogram Delay1ms
goto Dechi
call Delay1ms
decf PAUSEL,F
goto Loop1
Dechi
movf PAUSEH,F
btfsc STATUS,Z
goto Done
call Delay1ms
decf PAUSEH,F
decf PAUSEL,F
goto Loop1
Delay1ms ; Delay1ms produces a one millisecond delay
movlw .100 ; 100*10us=1ms
movwf LOOPCOUNT ; LOOPCOUNT<-100
Loop2
nop
nop
nop
nop
nop
nop
nop
decfsz LOOPCOUNT,F ; Time period necessary to execute loop Loop2
goto Loop2 ; equals 10us
Done
return ; Return to caller
; Subroutine: WriteEE
; Write a byte of data to EEPROM storage
; Inputs:
; GEAR - should be set to the GEAR number, which will be used as the EEPROM address
; W register - should contain the data to be stored
; Temporary:
; None
; Output:
; None
WriteEE
banksel EEDATA ; Select the bank of EEDATA
movwf EEDATA ; Data value to write
banksel GEAR
movf GEAR,W ; Use the GEAR number as the EEPROM address
banksel EEADR ; Select bank of EEADR
movwf EEADR ; Data memory address to write
banksel EECON1 ; Select bank of EECON1
bcf EECON1,EEPGD ; Point to DATA EEPROM mem (as opposed to PGM mem)
bsf EECON1,WREN ; Enable writes
banksel INTCON ; Select bank of INTCON
bcf INTCON,GIE ; Disable Global Interrupts
btfsc INTCON,GIE ; Global Interrupts really disabled?
goto $-2 ; NO, try again
banksel EECON2 ; Select bank of EECON2
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1,WR ; Set WR bit to begin write
btfsc EECON1,WR ; Wait for write to finish
goto $-1 ; looping until it is
bsf INTCON,GIE ; Enable Global Interrupts
bcf EECON1,WREN ; Disable writes
banksel 0 ; Select bank 0 now that we're all done
return ; Return to caller
; Subroutine: ReadEE
; Read a byte of data to EEPROM storage
; Inputs:
; GEAR - should be set to the GEAR number, which will be used as the EEPROM address
; Temporary:
; None
; Output:
; W register - contains the EEPROM data byte that has been read
ReadEE
banksel 0
movf GEAR,W ; Get GEAR number into the W register
banksel EEADR ; Select bank of EEADR
movwf EEADR ; Data memory address to read
banksel EECON1 ; Select bank of EECON1
bcf EECON1,EEPGD ; Point to data memory
bsf EECON1,RD ; EE Read
banksel EEDATA ; Select bank of EEDATA
movf EEDATA,W ; Get EEDATA into W register
banksel 0 ; Select bank 0 now that we're all done
return ; return to caller
; Subroutine: DoIPGCount
; Determine the number of IPG cycles that occur in the time it takes for a set number
; of VSS cycles to occur. This is essentially accomplished by:
; - Taking a snapshot of Timer0 counter
; - Resetting the VSS interrupt flag (i.e. setting VSSINT to 0x00)
; - Waiting for the VSS interrupt flag to be set (i.e. VSSINT will change to 0xFF)
; - Taking a second snapshot of Timer0 counter
; - Calculating the difference between the two Timer0 snapshots
; Inputs:
; None
; Temporary:
; TMR0_1 - 1st snapshot of Timer0 counter
; TMR0_2 - 2nd snapshot of Timer0 counter
; Output:
; W register - contains the number of IPG cycles that had occurred
DoIPGCount
clrf VSSINTS
clrf VSSINT
bcf INTCON,INTF ; Clear the 'INT' interrupt flag
bsf INTCON,GIE ; Enable global interrupts
movfw TMR0
movwf TMR0_1 ; Save the current contents of Timer0
btfss VSSINT,0 ; Now wait for the VSS interrupt flag to go high
goto $-1
movfw TMR0 ; The whole time that was happening, Timer0 was counting IPG cycles
movwf TMR0_2 ; So, save the current contents of Timer0 again
movfw TMR0_1
subwf TMR0_2,W ; Subtract the two Timer0 snapshots
bcf INTCON,GIE ; Disable global interrupts
btfsc INTCON,GIE ; Make sure.... are global interrupts really disabled now?
goto $-2 ; No, try again
return ; Return to caller with the count in the W register
; Subroutine: AvgIPGCount
; Call DoIPGCount 8 times, and calculate the average of the 8 results
; This routine assumes the Timings will never exceed an 8 bit result
; Inputs:
; None
; Temporary:
; IPGSUML - low order 8 bits of the 16 bit sum of IPG cycles
; IPGSUMH - high order 8 bits of the 16 bit sum of IPG cycles
; Output:
; W register - contains the averaged timings
AvgIPGCount
clrf IPGSUML ; Clear the variables that will be used
clrf IPGSUMH ; to hold the sum of the eight timings
call DoIPGCount ; Now go get a timing #1
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #2
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #3
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #4
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #5
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #6
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #7
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
call DoIPGCount ; Now go get a timing #8
addwf IPGSUML,F ; Add it to the rest
btfsc STATUS,C ; Did we have a carry
incf IPGSUMH,F ; Yes, so bump the high order 8 bits
rrf IPGSUMH,F ; Now we divide the sum by 8
rrf IPGSUML,F ; by shifting right 3 times
rrf IPGSUMH,F
rrf IPGSUML,F
rrf IPGSUMH,F
rrf IPGSUML,F
movfw IPGSUML ; Get the result into the W register
return ; Return to caller
; Subroutine: DoAmbient
; The ambient light sensor is a standard cadmium sulfide photo-cell, configured in a simple
; voltage divider network. The resulting voltage drop created by the photo-cell is connected
; to the PORTA RA2/AN2 pin, which has been configured as an analog input. Here we do an A/D
; conversion on that voltage.
; This routine is used to update an array of the 16 most recent A/D conversions.
; As the array fills, we wrap around to the beginning again. The values in the array will
; then be used in calculating a rolling average.
; Inputs:
; AMBIENTIX - The array index, pointing at the storage location of the next available location
; PORTA AN2 - The input voltage to do the A/D conversion on
; Temporary:
; None
; Output:
; AMBIENT0<->AMBIENTF - one of the 16 slots in the AMBIENT array, pointed to by AMBIENTIX
DoAmbient
movfw AMBIENTIX ; Get the current array index
movwf FSR ; Put it in the File Select Register
bsf ADCON0,ADON ; Turn on the A/D converter
call Delay1ms ; Wait for the A/D converter to settle
bcf PIR1,ADIF ; Clear the A/D interrupt flag
bsf ADCON0,GO ; Start an A/D conversion
btfsc ADCON0,GO_DONE ; Test the GO_DONE bit and wait until it is clear,
goto $-1 ; indicating the A/D conversion is done
bcf ADCON0,ADON ; Turn off the A/D converter
movfw ADRESH ; Get the A/D result into W
movwf INDF ; Save the result of the A/D conversion into the location pointed to by FSR
incf AMBIENTIX,F ; Bump the array index
btfsc AMBIENTIX,4 ; Have we reached the end of the 16 byte array yet?
bcf AMBIENTIX,4 ; Yes, so wrap back to the beginning
return ; Return to caller
; Subroutine: AvgAmbient
; Compute a rolling average of the 16 ambient sensor array samples
; Inputs:
; AMBIENT0<->AMBIENTF - The 16 byte AMBIENT array
; Temporary:
; AMBIENTSUML - Low order byte of the sum of the 16 array elements
; AMBIENTSUMH - High order byte
; Output:
; AMBIENTAVG - Holds the computed average
; W register - Holds the computed average
AvgAmbient
movlw low AMBIENT0 ; Get the memory address of the beginning of the array
movwf FSR ; Save it in the File Select Register (FSR)
clrf AMBIENTSUML ; Clear the high order byte of the sum
clrf AMBIENTSUMH ; Clear the low order byte of the sum
movfw INDF ; Get the data from the array entry pointed to by the FSR
addwf AMBIENTSUML,F ; Add it to the sum
btfsc STATUS,C ; Did the addition result in a carry
incf AMBIENTSUMH,F ; Yes, so bump the high order byte
incf FSR,F ; Point at the next array entry
btfss FSR,4 ; Have we done all 16 array entries yet?
goto $-6 ; No, do another
rrf AMBIENTSUMH,F ; Now we divide the sum by 16
rrf AMBIENTSUML,F ; by shifting right 4 times
rrf AMBIENTSUMH,F
rrf AMBIENTSUML,F
rrf AMBIENTSUMH,F
rrf AMBIENTSUML,F
rrf AMBIENTSUMH,F
rrf AMBIENTSUML,F ; Leaving the result in the low order byte of sum
movfw AMBIENTSUML ; Get the final result into W
movwf AMBIENTAVG ; Save the average
return ; Return to caller
; End subroutines
;---------------------------------------------------------------------------------------------
; Begin translate tables
ORG 0x300 ; Make sure to align translate table on a new page boundary
; Subroutine: Hexto7seg
; Take the binary value in W, which is what we want to have displayed on our LED display,
; and convert it to a bit pattern needed to turn on the right PORT pins to light the LED
; segments.
; The logic level of the PORTA RA7 pin is used to control which lookup table is used. If
; the user has installed his LED display in an upside-down position, then he will have
; installed the jump onto the 2 pin jumper header. This will drive the RA7 pin low.
; If the user has installed the LED display in the upright position, then he will have
; uninstalled the jumper. And RA7 will be high.
; Inputs:
; W register - the binary value representing the data to be displayed
; PORTA,RA7 - the two pin digit orientation jumper
; Temporary:
; None
; Output:
; W register - contains the bit pattern needed to turn on the segments of the LED, when
; the contents of W is later written to PORTB
Hexto7seg
btfss PORTA,7 ; Use the upside-down decodes if RA7 is low
goto UpsideDown
; PORTB output pins mapped to 7 segment LED display (upright)
; a
; -------
; f | | b
; | |
; -------
; e | g | c
; | |
; -------
; d
;
; RB0 = n/a - s/b low at all times
; RB1 = g
; RB2 = f
; RB3 = e
; RB4 = d
; RB5 = c
; RB6 = b
; RB7 = a
addwf PCL,f
retlw B'00000010' ; decode 0
retlw B'10011110' ; decode 1
retlw B'00100100' ; decode 2
retlw B'00001100' ; decode 3
retlw B'10011000' ; decode 4
retlw B'01001000' ; decode 5
retlw B'01000000' ; decode 6
retlw B'11100010' ; decode L
retlw B'11111100' ; decode "-" (indicates the clutch is pulled in)
UpsideDown
; PORTB output pins mapped to 7 segment LED display (upside-down)
; d
; -------
; c | | e
; | |
; -------
; b | g | f
; | |
; -------
; a
;
; RB0 = n/a - s/b low at all times
; RB1 = g
; RB2 = f
; RB3 = e
; RB4 = d
; RB5 = c
; RB6 = b
; RB7 = a
addwf PCL,f
retlw B'00000010' ; decode 0
retlw B'11110010' ; decode 1
retlw B'00100100' ; decode 2
retlw B'01100000' ; decode 3
retlw B'11010000' ; decode 4
retlw B'01001000' ; decode 5
retlw B'00001000' ; decode 6
retlw B'00011110' ; decode L
retlw B'11111100' ; decode "-" (indicates the clutch is pulled in)
end
merenat- Nuevo Usuario
- Mensajes : 9
Fecha de inscripción : 18/02/2009
Re: Ayudadme con un "Indicador de marchas para moto según pulsos velocidad y r.pm."
voy haciendo pruebas, de momento he modificado para que guarde capturas en la epprom para saber que va haciendo. Pero las tengo que sacar de picklab a mano y cambiar de hex a decimal para meterlo en una hoja de calculo de libreoficce. Hay alguna forma de copiar los datos mas rapido y luego pasarlo a dec con la propia hoja de calculo? Edito: Con la función =HEXADEC(valor) y si abro con gedit el hex obtengo esto:
:104200000600AA00AA00AA00AA00AA00AA00CC00E0
:10421000FF00780053004700370031003000FF00F6
:10422000FF007B00510043003A0038003300FF00DC
:10423000FF007700540042003A0035002D00FF00D7
:10424000FF007400520043003C0035003200FF00C4
:10425000FF00770053004100380035002E00FF00BA
:10426000FF007D0059004300370036002F00FF009B
:10427000FF00770057004100390034002E00FF0096
:10428000FF0074005B004B00380033003200FF0079
:10429000FF0074004E003F003C0031002F00FF0083
:1042A000FF00760053003E003C0033003000FF006A
:1042B000FF00790051003E00370031002F00FF0061
:1042C000FF007800560043003B0034002D00FF0043
:1042D000FF007A0058004100390036003000FF002E
:1042E000FF0075004E0040003C0036002E00FF002D
:1042F000FF00730054004100380034003000FF001C
:10430000FF00750052004000390033003100FF000B
:10431000FF00750051003D00380038002E00FF00FE
:10432000FF00720057004200370032003000FF00EB
:10433000FF0072005000440035003D002D00FF00DA
:10434000FF0072005A0042003D0033003000FF00C1
:10435000FF00FF00FF00FF00FF00FF00FF00FF0065
:10436000FF00FF00FF00FF00FF00FF00FF00FF0055
:10437000FF00FF00FF00FF00FF00FF00FF00FF0045
:10438000FF00FF00FF00FF00FF00FF00FF00FF0035
:10439000FF00FF00FF00FF00FF00FF00FF00FF0025
:1043A000FF00FF00FF00FF00FF00FF00FF00FF0015
:1043B000FF00FF00FF00FF00FF00FF00FF00FF0005
:1043C000FF00FF00FF00FF00FF00FF00FF00FF00F5
:1043D000FF00FF00FF00FF00FF00FF00FF00FF00E5
:1043E000FF00FF00FF00FF00FF00FF00FF00FF00D5
:1043F000FF00FF00FF00FF00FF00FF00FF00FF00C5
estan los numeros intercalados con 00 pero ya me pierdo de como sacarlos.
:104200000600AA00AA00AA00AA00AA00AA00CC00E0
:10421000FF00780053004700370031003000FF00F6
:10422000FF007B00510043003A0038003300FF00DC
:10423000FF007700540042003A0035002D00FF00D7
:10424000FF007400520043003C0035003200FF00C4
:10425000FF00770053004100380035002E00FF00BA
:10426000FF007D0059004300370036002F00FF009B
:10427000FF00770057004100390034002E00FF0096
:10428000FF0074005B004B00380033003200FF0079
:10429000FF0074004E003F003C0031002F00FF0083
:1042A000FF00760053003E003C0033003000FF006A
:1042B000FF00790051003E00370031002F00FF0061
:1042C000FF007800560043003B0034002D00FF0043
:1042D000FF007A0058004100390036003000FF002E
:1042E000FF0075004E0040003C0036002E00FF002D
:1042F000FF00730054004100380034003000FF001C
:10430000FF00750052004000390033003100FF000B
:10431000FF00750051003D00380038002E00FF00FE
:10432000FF00720057004200370032003000FF00EB
:10433000FF0072005000440035003D002D00FF00DA
:10434000FF0072005A0042003D0033003000FF00C1
:10435000FF00FF00FF00FF00FF00FF00FF00FF0065
:10436000FF00FF00FF00FF00FF00FF00FF00FF0055
:10437000FF00FF00FF00FF00FF00FF00FF00FF0045
:10438000FF00FF00FF00FF00FF00FF00FF00FF0035
:10439000FF00FF00FF00FF00FF00FF00FF00FF0025
:1043A000FF00FF00FF00FF00FF00FF00FF00FF0015
:1043B000FF00FF00FF00FF00FF00FF00FF00FF0005
:1043C000FF00FF00FF00FF00FF00FF00FF00FF00F5
:1043D000FF00FF00FF00FF00FF00FF00FF00FF00E5
:1043E000FF00FF00FF00FF00FF00FF00FF00FF00D5
:1043F000FF00FF00FF00FF00FF00FF00FF00FF00C5
estan los numeros intercalados con 00 pero ya me pierdo de como sacarlos.
merenat- Nuevo Usuario
- Mensajes : 9
Fecha de inscripción : 18/02/2009
Temas similares
» Ayuda para añadir pics para simular en Ktechlab.
» Gedit_Pic-IDE: plugin para convertir Gedit en una IDE para PIC
» librería ADC para PIC-GCC
» Libreria para PIC
» Bug en la librería ADC para 18F
» Gedit_Pic-IDE: plugin para convertir Gedit en una IDE para PIC
» librería ADC para PIC-GCC
» Libreria para PIC
» Bug en la librería ADC para 18F
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.
|
|