11-29-2016, 12:06 PM
|
#31 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
Thanks. I picked up a mega 2560 today as I couldn't find the relevant flags to get it to compile on any of my other boards. The goal for me is to use a pro mini -- see photog with current hardware, still more miniaturization to come. I was using a Pi 0, but the graphics were jerky -- I might still do something based on the Pi0 but the car interface board/shield will need to be redone for that form factor.
Parallax LCD using a single pin is very attractive for portability -- does that mean the tx pin cannot be used for json output to the Pi? Or is it as straightforward as dedicating another pin for output?
|
|
|
Today
|
|
|
Other popular topics in this forum...
|
|
|
11-29-2016, 12:20 PM
|
#32 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
One more item: You aren't required to pass 3 values into the JSON file, n values from 0 to at least 10. I like to keep it simple, so it's 3 ranges for each, 2 measures for the first graph (total and bingo fuel remaining), 1 measure for the 2nd (reserve range) and 2 for the 3rd (trip, tank). (Measures are the orange bars), and a single marker for each (marker is the floating white bar).
I will adjust the colors, for some reason I left the 3rd measure white, which looks awful.
|
|
|
11-29-2016, 05:55 PM
|
#33 (permalink)
|
MPGuino Supporter
Join Date: Oct 2010
Location: Hungary
Posts: 1,807
iNXS - '10 Opel Zafira 111 Anniversary Suzi - '02 Suzuki Swift GL
Thanks: 830
Thanked 708 Times in 456 Posts
|
Quote:
Originally Posted by skybolt
Thanks. I picked up a mega 2560 today as I couldn't find the relevant flags to get it to compile on any of my other boards. The goal for me is to use a pro mini -- see photog with current hardware, still more miniaturization to come. I was using a Pi 0, but the graphics were jerky -- I might still do something based on the Pi0 but the car interface board/shield will need to be redone for that form factor.
|
What programming environment are you using for programming your Arduino? I'm using the basic IDE, and telling it what board to use. If you're using anything else, you're going to want to tell your programmer to use an Atmel Mega328p to support your Arduino Pro.
Quote:
Originally Posted by skybolt
Parallax LCD using a single pin is very attractive for portability -- does that mean the tx pin cannot be used for json output to the Pi? Or is it as straightforward as dedicating another pin for output?
|
Yah, pretty much. You could use a TWI bus LCD module instead, which would leave your serial TX pin free to use for the JSON output.
Quote:
Originally Posted by skybolt
One more item: You aren't required to pass 3 values into the JSON file, n values from 0 to at least 10. I like to keep it simple, so it's 3 ranges for each, 2 measures for the first graph (total and bingo fuel remaining), 1 measure for the 2nd (reserve range) and 2 for the 3rd (trip, tank). (Measures are the orange bars), and a single marker for each (marker is the floating white bar).
I will adjust the colors, for some reason I left the 3rd measure white, which looks awful.
|
It's no big deal for me - I just want the MPGuino code to be able to handle being able to output whatever numbers are required for JSON (or any other conceivable) output.
Turns out that each regular number required five 64-bit divides to turn it into an output string. That'd be twenty 64-bit divides to display the numbers, versus between 4 and 8 for the actual value calculations themselves. Going to test some code tonight or tomorrow which will reduce that down to one 64-bit divide for regular numbers. That should give about an 80% speed improvement. CPU loading has already gone down from almost 102% before yesterday's experimentation, to about 63% after last night. I should hopefully see the CPU loading go down to about 13%. This will enable you to use 4 loops per second, instead of the current 2 loops per second.
|
|
|
11-29-2016, 09:28 PM
|
#34 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
I'm using the standard IDE. The original code I based my mods on was only compatible with v.1.0.6 of the IDE, and I didn't bother to try and update it ... just one more reason I like your code is that it's compatible with 1.6.x
If you set your IDE for an Uno, Pro or Pro Mini you'll see that disabling the define flags for the 2620 and two or three of the serial tags, there's also an error message
Quote:
main.cpp:9709: error: 'PINK' was not declared in this scope
lastPINKstate = PINK; // initialize last PINK state value so as to not erroneously detect a keypress on start
|
It may be something simple, my guess if you haven't tested it for other boards yet. No biggie, that's what pushed me over the edge to buy the mega. Just stumbled across a new board today, the tinycircuits tiny arduino -- it's 8MHz and basically a pro mini board, but it's stackable using a 2cm x 1cm connector -- it'll help me miniaturize but not lose functionality -- and no need for 20+ pins soldered to the 'duino.
|
|
|
12-09-2016, 08:51 PM
|
#35 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
The code is great! I've got it running, configured it to use standard buttons, (although I now have the parallax button as well, which makes more sense for long-term use and mounting remotely.
I plugged it in to the car today, and ... discovered you are simulating data! I've spent a few minutes checking for a flag like "sim" or "sample". I figured this out when I noticed the data approximates 74.9mph and 2.81gph, whether or not the injector and speed sensor are connected to anything.
How to I turn off simulated data? I'm going to check the individual return routines to see if there's evidence of a flag there.
|
|
|
The Following User Says Thank You to skybolt For This Useful Post:
|
|
12-12-2016, 02:15 PM
|
#36 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
ah HA!! Found it
Code:
#ifdef useDebugReadings
tripArray[(unsigned int)(rawIdx)].collectedData[(unsigned int)(rvInjCycleIdx)] = (t2CyclesPerSecond / loopsPerSecond);
tripArray[(unsigned int)(rawIdx)].collectedData[(unsigned int)(rvInjOpenCycleIdx)] = ((16391ul * processorSpeed) / (loopsPerSecond * 10));
tripArray[(unsigned int)(rawIdx)].collectedData[(unsigned int)(rvVSScycleIdx)] = (t2CyclesPerSecond / loopsPerSecond);
tripArray[(unsigned int)(rawIdx)].collectedData[(unsigned int)(rvInjPulseIdx)] = (20ul / loopsPerSecond);
tripArray[(unsigned int)(rawIdx)].collectedData[(unsigned int)(rvVSSpulseIdx)] = (208ul / loopsPerSecond);
timerCommand |= tcWakeUpOnEngine; // tell system timer to wake up the main program
#endif
Updates to follow as I run it with live data and start tinkering with the code.
My first order of action will be to modify the loop time to allow for .01 sec resolution during the acceleration times, then see how badly that affects RPM, then look at putting in an RPM buffer so that dropping to zero takes 3 or 4 shortened loops.
|
|
|
12-12-2016, 03:20 PM
|
#37 (permalink)
|
MPGuino Supporter
Join Date: Oct 2010
Location: Hungary
Posts: 1,807
iNXS - '10 Opel Zafira 111 Anniversary Suzi - '02 Suzuki Swift GL
Thanks: 830
Thanked 708 Times in 456 Posts
|
updated to latest code
Quote:
Originally Posted by skybolt
My first order of action will be to modify the loop time to allow for .01 sec resolution during the acceleration times, then see how badly that affects RPM, then look at putting in an RPM buffer so that dropping to zero takes 3 or 4 shortened loops.
|
Why? All acceleration times already have about 0.001 second resolution, as they stand now.
Do you want to change the overall period of the instantIdx trip variable? That is done by changing the loop time. Currently, it's set to 500 ms, but could be set to 250 ms (4 loops/sec) without overloading the loop. However, going beyond 4 loops/sec will not have the desired effect. Data gathering will not be affected, but your output time resolution will suffer as the loops themselves get overloaded.
I guess I really have no idea what you want to accomplish by adding this RPM buffer.
One more thing - you'll probably want to use the attached code. It's the latest version, but it does have some untested modifications that I have to verify.
Update: The current version of my MPGuino code may be found here.
Last edited by t vago; 01-06-2017 at 01:14 AM..
Reason: provided link to current code
|
|
|
12-13-2016, 08:07 PM
|
#38 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
Quote:
All acceleration times already have about 0.001 second resolution, as they stand now.
|
Well, then there's no reason to change the loop time. I knew you took out the delay, but I assumed you used the timer to pause execution of the loop ... I never bothered to look. Based on your statement, the main loop is obviously able to repeat very quickly (some multiple of clock speed, of course).
Under the old code, the acceleration time was checked once per loop, during the doDisplay event which in turn called drag::Update. So, a user could hit 30 mph at, say 2.100 seconds, but checking for the condition could be delayed up to the length of looptime, in this case it could read 2.3499.
To improve accuracy I skipped the delay if drag_running or drag_waiting was true. This could drop the looptime to at most 110ms, or if I'd never called the LCD display routine, 7ms.
This caused its own problem!! Mainly, while waiting to start loop time is between 7 and 110ms. The engine is idling at 1200 rpm or 20 rps, or every 50ms. Our #1 injector fires once every other revolution, or once every 100ms. Also, our injector is open for a very short time, has a 500microsecond "settle" time -- long way of saying rpm flashes to 0 when we have a loop without an injector fire, and higher when we have two fires per loop. This also throws of calculation of instant mpg. It doesn't hurt current/tank mpg since those are based on total distance/fuel ticks, all of which remain accurate - but the displays jump around. Based on my empirical testing, anything below 2300 rpm would show this behavior -- so I started working on logic similar to Flip to EOC data when stopped - after 6 or so loops, basically saying "don't return 0 rpm unless 0 rpm has been reported N number of times.
The RPM buffer is to solve a problem that no longer exists as long as acceleration times are accurate to within .001, or actually accurate to looptime, which I'm guessing is greater than .001 second.
|
|
|
12-14-2016, 01:52 AM
|
#39 (permalink)
|
MPGuino Supporter
Join Date: Oct 2010
Location: Hungary
Posts: 1,807
iNXS - '10 Opel Zafira 111 Anniversary Suzi - '02 Suzuki Swift GL
Thanks: 830
Thanked 708 Times in 456 Posts
|
Quote:
Originally Posted by skybolt
Well, then there's no reason to change the loop time. I knew you took out the delay, but I assumed you used the timer to pause execution of the loop ... I never bothered to look. Based on your statement, the main loop is obviously able to repeat very quickly (some multiple of clock speed, of course).
|
You are correct, in a sense. The main loop is very much dependent on the system timer, but not in the usual sense.
This is what actually happens: - The main loop senses that the loop time count has expired
- The main loop then tells the timer to start another loop time count
- The main loop then disables interrupts and performs a transfer of trip data from the raw trip index to the instant trip index. It will then re-enable interrupts in order to continue to read injector events and VSS events and keypresses.
- The main loop then processes all remaining trip indexes from the instant index. This is the index that has a period equal to the loop time. Change the loop to 4x a second, the loop time goes to 250 ms. It's normally at 500 ms.
- The main loop then performs any display screen updating. This is also when the outputJSON routine is called.
- Any other housekeeping is performed at this time.
- The main loop will then just sit there and wait for the loop time count to expire. The process then begins all over again.
If the main loop detects a keypress, it will immediately stop waiting for the loop time count to expire, and it will immediately execute the related keypress. This may cause the display screen to update instantaneously, but no trip indexes will be touched.
The instant trip index is somewhat misnamed. It is actually an average trip index, but averaged only over a period of the loop time. To our eyes, it's pretty much instantaneous.
The only time the instant trip index might have a period greater than the loop time, is when either the display output, JSON output, logging output, debugging output (if enabled), or housekeeping functions take longer than the loop time. There is no danger to recording the data itself, as the MPGuino code will still accurately gather injector event and VSS event data, and will still generate reliable current trip, tank trip, and other trip functionality. It just might display instant trip functions in a somewhat peculiar manner.
Quote:
Originally Posted by skybolt
Under the old code, the acceleration time was checked once per loop, during the doDisplay event which in turn called drag::Update. So, a user could hit 30 mph at, say 2.100 seconds, but checking for the condition could be delayed up to the length of looptime, in this case it could read 2.3499.
|
Yah, that was one of the first things I noticed with the existing 0.86 MPGuino code, and one of the first things I canned by having the system timer take care of doing timing and having the main loop just poll a status flag to see if the loop had completed. It also allowed instantaneous keypress response as described above.
The next thing I did was to have the main loop truly become the main loop. The 0.86 code shifted to a secondary "main" loop whenever a parameter was being cycled for editing, and then went to a third "main" loop whenever the parameter was actually being edited. Trip data was not gathered during the execution of these loops. This would also result in strange readings once the code execution returned to the main loop.
My code, in contrast, always transfers trip index data per loop, even if parameters are being edited. I am in fact thinking about making the parameter edit section a bit more user friendly by allowing the display and editing of numbers that should have a decimal point in them. They currently show up as "(whatever)*1000" in the parameter edit section.
Quote:
Originally Posted by skybolt
To improve accuracy I skipped the delay if drag_running or drag_waiting was true. This could drop the looptime to at most 110ms, or if I'd never called the LCD display routine, 7ms.
This caused its own problem!! Mainly, while waiting to start loop time is between 7 and 110ms. The engine is idling at 1200 rpm or 20 rps, or every 50ms. Our #1 injector fires once every other revolution, or once every 100ms. Also, our injector is open for a very short time, has a 500microsecond "settle" time -- long way of saying rpm flashes to 0 when we have a loop without an injector fire, and higher when we have two fires per loop. This also throws of calculation of instant mpg. It doesn't hurt current/tank mpg since those are based on total distance/fuel ticks, all of which remain accurate - but the displays jump around. Based on my empirical testing, anything below 2300 rpm would show this behavior -- so I started working on logic similar to Flip to EOC data when stopped - after 6 or so loops, basically saying "don't return 0 rpm unless 0 rpm has been reported N number of times.
|
That makes sense now.
Quote:
Originally Posted by skybolt
The RPM buffer is to solve a problem that no longer exists as long as acceleration times are accurate to within .001, or actually accurate to looptime, which I'm guessing is greater than .001 second.
|
For acceleration testing, I have created 4 separate trip variables, and they all operate independently of the main loop. The first trip variable records the 0-30 MPH portion, the second records the 0-60 MPH portion, the third trip variable records the 1/4 mile portion, and the fourth trip variable records the true instant speed when the vehicle has traveled 1/4 mile.
The first three trip variables can be treated exactly as the current or tank trip variables. You can get the total period, which corresponds to either 0-30 time, 0-60 time, or 1/4 mile time. You can get total fuel consumed for each of these trips, as well as average speed, distance traveled, average engine speed, fuel economy, fuel consumed, fuel consumption rate, and so on.
The fourth trip variable is special, as it actually does capture the instantaneous vehicle speed when the 1/4 mile marker is reached. This is defined as a single vehicle pulse, its corresponding VSS pulse period measurement corresponds to the number of timer2 ticks per pulse. For 75 MPH using 10000 pulses per mile, this VSS pulse period value would be 1200, and for about 128.6 MPH, this value would be 700. For 119.36 MPH, this would be 754.
Differing values of pulses/mile will change the VSS pulse period value, but you should not see any problem.
All of these acceleration test trip variables operate completely independent of the loop time. All the accel test data is gathered in the background, and as long as the main loop does not disable interrupts for too long (say, for 100 microseconds), then the accel test data will not be corrupted. That's to ensure that consecutive vehicle speed pulses and injector event pulses are correctly captured.
|
|
|
12-14-2016, 12:35 PM
|
#40 (permalink)
|
deviant
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69
Thanks: 12
Thanked 47 Times in 35 Posts
|
Quote:
Originally Posted by t vago
Yah, that was one of the first things I noticed with the existing 0.86 MPGuino code, and one of the first things I canned by having the system timer take care of doing timing and having the main loop just poll a status flag to see if the loop had completed.
|
Excellent work. I always thought the original code was very ham-fisted.
Quote:
Originally Posted by t vago
The first three trip variables can be treated exactly as the current or tank trip variables. You can get the total period, which corresponds to either 0-30 time, 0-60 time, or 1/4 mile time.
|
Are you grabbing both 0-30 and 0-60? I originally had it 0-speed, where speed was configurable as a parameter. Catching both removes the need for a parameter -- the only edge case I can think of is calculating 0-100, which I wouldn't even do. I assume for metric you're taking 0-50kph and 0-100kph, which are typically the values quoted by manufacturers.
I still haven't created a working mpguignio shield (car-to-duino interface, basically two resistors and two zener diodes, with a voltage regulator for full compatibility). Once I've figured out how I messed up so simple a design I'll start in-car testing. My other choice is to simply overwrite my production MPiGuino, but it's a pain to deploy code to that one given the short wires involved, and there are benefits to having a dedicated dev mule that can be hooked up to the car.
Quote:
The fourth trip variable is special, as it actually does capture the instantaneous vehicle speed when the 1/4 mile marker is reached.
|
Only catching instantaneous at the 1/4 mile causes a problem -- many ecomodders won't keep accelerating all the way to 1/4 mile, nor do I when the 1/4 mile time approaches 100mph and I'm testing on a freeway on-ramp. 0-60 is relatively safe and perfectly legal (in a 60mph zone). We don't want to capture end speed if it's less than maximum speed during the run. I'd originally solved this by taking updating trap_speed with MAX(speed, trap_speed), but as I recall you terminate the run when the speed begins to drop.
I believe your approach will work, but real-world driving may result in eco acceleration runs having minor dips in speed, causing early termination of the run. Once I have in-car testing running I will report. Slow shifting in particular can cause a loss of at least 1 mph. I expect to be able to cobble together, today, a breadboard version of a working car-to-duino interface. I've already verified I can push JSON from the new code to my in-car display unit, so in-car testing will be very full-featured.
|
|
|
|