Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Maximite Tacho with LCD
Author | Message | ||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
I put together a little tacho program and circuit for the Maximte yesterday. I needed to quickly measure the RPM of a alternator I was testing ( http://www.thebackshed.com/forum/forum_posts.asp?TID=3504&PN =1&TPN=11 ) and my usual tools were letting me down. I do have a Oatley Electronics K117 opto-tacho kit, but it needed calibration and was very slow to respond, I no longer have a copy of the instructions, plus Oatley dont have them on their web site either unfortunately. But the K117's optic circuit was working, and it flashed a LED for each revolution of the alternator. So I connected the LED to a opto coupler, feeding pin 18 of the Maximite. On pin 17 I conneced a LED, to flash with each revolution, and on pins 11 to 16 is a LCD module. This circuit is copied from the LCD.pdf file, with a few additions on pin 17 and 18. The LCD module displays the cycle time in ms, the duty cycle ( LED off in this case ), the frequency in Hz and the RPM. Here's to code. Its mostly the LCD routine included with the Maximite samples, with the tacho routines from 100 to 400. 100 SETPIN 17,8 110 SETPIN 18,2 120 PIN(17)=0 130 GOSUB 11000 ' Initialise the LCD 140 LCD_line1$ = "Waiting for " 150 LCD_line2$ = "Signal " 160 GOSUB 12000 170 ' 180 ' Main Loop 190 ' 200 PIN(17)=1 210 DO WHILE PIN(18)=1 220 LOOP 230 StartTime=TIMER 240 DO WHILE PIN(18)=0 250 LOOP 260 MidTime=TIMER 270 PIN(17)=0 280 DO WHILE PIN(18)=1 290 LOOP 300 TotalTime=TIMER-StartTime 310 IF TotalTime>0 THEN 320 DutyCycle=100/TotalTime*(MidTime-StartTime) 330 LCD_line1$=STR$(INT(TotalTime)) + "ms " + STR$(INT(DutyCycle)) + "% Duty " 340 TotalTime=TotalTime/1000 350 Hz=1/TotalTime 360 RPM=Hz*60 370 LCD_line2$=FORMAT$(Hz,"%.1f") + "Hz " + FORMAT$(RPM,"%.1f") + "RPM " 380 ENDIF 390 GOSUB 12000 400 GOTO 200 11000 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''' 11010 ' Initialise the LCD 11020 ' 11030 FOR i = 11 TO 16 : SETPIN i, 9 : NEXT i 11040 _LCD_byte = &B0011 : GOSUB 13090 : PAUSE 5 ' reset 11050 _LCD_byte = &B0011 : GOSUB 13090 : PAUSE 5 ' reset 11060 _LCD_byte = &B0011 : GOSUB 13090 : PAUSE 5 ' reset 11070 _LCD_byte = &B0010 : GOSUB 13090 : PAUSE 2 ' 4 bit mode 11080 _LCD_byte = &B00101100 : GOSUB 13000 ' 4 bit, 2 lines 11090 _LCD_byte = &B00001100 : GOSUB 13000 ' display on, no cursor 11100 _LCD_byte = &B00000110 : GOSUB 13000 ' increment on write 11110 _LCD_byte = &B00000001 : GOSUB 13000 ' clear display 11115 PAUSE 2 11120 RETURN 12000 ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''' 12010 ' send the two lines to the LCD 12030 ' 12040 _LCD_byte = &H80 : GOSUB 13000 ' select the 1st line 12050 FOR _LCD = 1 TO 16 12060 _LCD_byte = ASC(MID$(LCD_Line1$, _LCD, 1)) 12070 PIN(11) = 1 : GOSUB 13000 ' send the character 12080 NEXT _LCD 12090 _LCD_byte = &B11000000 : GOSUB 13000 ' select the 2nd line 12100 FOR _LCD = 1 TO 16 12110 _LCD_byte = ASC(MID$(LCD_Line2$, _LCD, 1)) 12120 PIN(11) = 1 : GOSUB 13000 ' send the character 12130 NEXT _LCD 12140 RETURN 13000 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''' 13010 ' Send a byte to the LCD 13020 ' the data to be sent is in _LCD_byte 13030 ' 13040 PIN(13) = _LCD_byte AND &B00010000 ' output the 1st 4 bits 13050 PIN(14) = _LCD_byte AND &B00100000 13060 PIN(15) = _LCD_byte AND &B01000000 13070 PIN(16) = _LCD_byte AND &B10000000 13080 PIN(12) = 1 : PIN(12) = 0 ' tell lcd to accept data 13090 ' Entry point to send just 4 bits to the LCD 13100 PIN(13) = _LCD_byte AND &B00000001 ' output the 2nd 4 bits 13110 PIN(14) = _LCD_byte AND &B00000010 13120 PIN(15) = _LCD_byte AND &B00000100 13130 PIN(16) = _LCD_byte AND &B00001000 13140 PIN(12) = 1 : PIN(12) = 0 : PIN(11) = 0 ' tell lcd to accept data 13150 RETURN Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
Ray B Senior Member Joined: 16/02/2007 Location: AustraliaPosts: 219 |
Excellent example of what can be achieved with a MM and something well documented from which others can learn. We need more of what has been achieved. RayB from Perth WA |
||||
crackerjack Senior Member Joined: 11/07/2011 Location: AustraliaPosts: 164 |
Excellent - this is what the Maximite is all about: rapid turnaround from idea to implementation. Gizmo's post is in the great spirit of this Forum in sharing code, ideas and circuits - thanks for this and for hosting this forum of opportunities to share and learn. |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
Thanks guys. I do see the Maximite as a tool more than a computer, and its perfect for little applications like this, lots of I/O pins and easy to program. There is a little timing problem I'll look at tomorrow. It reads fast. At 1.6Hz it reads 1.8Hz, and it gets worse as the frequency goes up, at 8.7Hz its reading 15.6Hz. Maybe a timing issue in the Maximite, though the DO WHILE PIN() loops are not the best way to do this sort of thing. I might look at using the interupts instead. Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
seco61 Senior Member Joined: 15/06/2011 Location: AustraliaPosts: 205 |
Hi Glenn. Yes, you will definitely have to move to using the interrupts. In the current code, the StartTime variable is being set after the LCD update routines. The LCD update routine (and associated calculations) will take a relatively constant time. The faster the pulses arrive, the later in the cycle the StartTime value is set - therefore giving a "shorter" TotalTime. Hence the frequency increases.... Regards Gerard (vk3cg/vk3grs) |
||||
Talbit Senior Member Joined: 07/06/2011 Location: AustraliaPosts: 210 |
Gizmo, How does your LCD circuit work, because it's wired up incorrectly? See Geoffs' latest circuit. He has corrected his mistake. Talbit Talbit |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
Ah, yes, your right, I just grabed the circuit from the original PDF, but as you said its wrong. My LCD is wired up correctly. I'll update that imaage later. Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
sparkey Senior Member Joined: 15/06/2011 Location: AustraliaPosts: 819 |
i`m waiting on some new code from gerard for my inverter.. as i do have it running if only to generate a square wave or pulse width -mod ... how ever you see it... and also to have the few results i have on screen in the program like adj`s freq and m`s`ratio and main battery voltage going to try and mod the code my self soon ..as i am not very good with code ..i`m more of an anolouge tech`y really .. going to get a small screen prolly one of those seven inch lcd`s ... to me its all about current .....interesting stuff there gizzmo technicians do it with least resistance |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
The circuit diagram is correct now. Looking into using the interupts, but I have a question. What if a interupt routine is running, and its triggered again before its finished ( ireturn )? Will it restart, or will we have two routines, which could be dangerous for RAM? Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
seco61 Senior Member Joined: 15/06/2011 Location: AustraliaPosts: 205 |
Hi Glenn. When a MMBasic interrupt routine is executing, no other MMBasic interrupt routine will be executed until the currently running routine has completed (ie the IRETURN statement is executed). At that point the interrupt check routine will run and if there is a matching condition to trigger a MMBasic interrupt routine it will be invoked. All interrupts in MMBasic have a relative priority and the interrupt check routine always starts its check with the highest priority interrupt. Regards Gerard (vk3cg/vk3grs) |
||||
sparkey Senior Member Joined: 15/06/2011 Location: AustraliaPosts: 819 |
sorry excuse me to interupt ... i have been playing round with my inverter program and starting to "setpin" for the extra voltges that i want to measure ...getting there regards sparkey ... technicians do it with least resistance |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
Thanks for clearing that up Gerard. I have another question, more of a "Best Practices", thats applicable to this project. If my program revolves around one interupt, and its always waiting for this interupt to do its "thing", then what should it be going in the mean time? eg.. 10 SETPIN 18,6,100 ' the interupt 20 goto 20 100 ' Do stuff 110 ireturn Line 20, where the Maximite is just waiting. Is there a best programming practice for a loop thats does nothing other than loop. Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
seco61 Senior Member Joined: 15/06/2011 Location: AustraliaPosts: 205 |
Hi Glenn. The following is just my opinion, and there may be other ways to do it as well. I would have your interrupt routine doing the absolute minimum amount of processing possible. In this case it would be to store the current timer value and then set a flag/state variable that the main program will interrogate. The main program would loop checking the flag/state variable. When the appropriate "state" is set it would then perform its calculations and update the LCD display. As you are interested in the time of both the low-to-high and high-to-low transistions, it may be applicable to tie two input pins together and have one set to interrupt on low-high and the other set to interrupt on high-low. The 2 interrupt routines would set their timer variables and the main program would perform the work as above. Regards Gerard (vk3cg/vk3grs) |
||||
Gizmo Admin Group Joined: 05/06/2004 Location: AustraliaPosts: 5078 |
Thanks Gerard I'll look into that, would be more efficient. This code works accurately, but not the best solution. It updates the LCD on every 2nd revolution. 100 SETPIN 17,8 110 SETPIN 18,6,500 120 PIN(17)=0 130 GOSUB 11000 ' Initialise the LCD 140 LCD_line1$ = "Waiting for " 150 LCD_line2$ = "Signal " 160 GOSUB 12000 170 ' 180 ' Do nothing loop 190 ' 200 goto 200 490 ' 500 ' Timing routine 501 ' 510 TIMER=0 515 PIN(17)=1 520 DO WHILE PIN(18)=1 530 LOOP 540 MidTime=TIMER 550 PIN(17)=0 560 DO WHILE PIN(18)=0 570 LOOP 580 TotalTime=TIMER 590 IF TotalTime>0 THEN 600 DutyCycle=100/TotalTime*MidTime 605 LCD_line1$=STR$(INT(TotalTime))+"ms "+STR$(INT(DutyCycle))+"% Duty " 610 TotalTime=TotalTime/1000 620 Hz=1/TotalTime 630 RPM=Hz*60 640 LCD_line2$=FORMAT$(Hz,"%.1f") + "Hz " + FORMAT$(RPM,"%.1f") + "RPM " 645 gosub 12000 650 ENDIF 660 Pause 1 ' to make sure the pulse has passed 670 ireturn LCD routines not shown Glenn The best time to plant a tree was twenty years ago, the second best time is right now. JAQ |
||||
Print this page |