|
Post by littlejo44 on Jun 14, 2020 9:57:39 GMT
Sketch with timing problem.. Hi Rowan.. (I’ve copied most of this from an earlier post to put everything into context.. ) Well..I tried..but every time I tried to introduce either the existing code in a different location, or your new code, into the sketch, it wouldn't compile, coming up with errors saying, for example, that various interrupts had 'not been declared in this scope'..so, as I stand a good chance of making things much worse, please have a look at the code for me.. If it can't be done, I'll abandon the gps speed idea.. Notes on the sketch.. With the sketch loaded, and with no input at all to SS, the ramp is extremely erratic..for example, when throttling up quickly from (say) 35% to (say) 75%, the ramp advances in definite slow bursts of around a second with about a second space between the bursts! (Few seconds of vid to follow) ..The Throttle is also slow to react.. Please note...in this sketch, the 'SpeedMPH' value is intentionally duplicated into the rpm value...Our telemetry software has a box to check when using the gps 'speed'. input, that will set it, after entering the gear ratio (obviously only works for single gear car), to calculate the rpm..(again, in the absence of the rpm sensor feed) Line 656 is where the SSreceive lines are.. Line 1311 is where (in this version) the usual 'SpeedMPH' feed originates for our telemetry stream? When uncommented and using wheel sensor pulses, this works fine.. I haven't (knowingly!) done anything to the BT part of the sketch..other than put a ‘1’ after the Debug you mentioned.. The GPS inputs the speed every two seconds or so, but the timing issues all happen with no input at all.. I won't get many marks out of ten for presentation, though.. I was going to tidy it up after it’s working ok☹️.. Please don't waste too much of your time on this..It's not vitally important, but it would be a big step on that 'learning curve' if I could get it working..thank you…John
|
|
|
Post by littlejo44 on Jun 14, 2020 10:04:43 GMT
Link to Throttle scope vid..If you listen to the sound, you can hear the motor responding...
|
|
|
Post by littlejo44 on Jun 14, 2020 15:47:29 GMT
...Tried substituting the on board serial RX, instead of SS, but, in that position in the sketch the timing was affected the same way.☹️.J
|
|
|
Post by keduro on Jun 15, 2020 10:29:29 GMT
Good morning John. I've taken a wee liberty and looked at your code. I am pretty confident that the problem lies in this code: { if (mySerial.available() > 0) {
mySerial.read();
}
SpeedMPH = mySerial.parseFloat();
if (SpeedMPH < 1)
SpeedMPH = 0;
}
which you call every 2 seconds (CSV_DATA_TRANSMIT_INTERVAL) in the main loop. "if (mySerial.available() > 0) { mySerial.read(); }" checks if there is any received data in the buffer and then immediately removes it!! (the read does that). Then "SpeedMPH = mySerial.parseFloat();" is executed. With no data now in the buffer parseFloat, which is a blocking function, will wait for a character sequence that looks like a floating point number to arrive in the buffer. If data is received, it will return the floating point value, however, if no data is received then "parseFloat" will timeout after the default period of 1000ms and return the value 0. I very much suspect that this 1s timeout is behind " the ramp advances in definite slow bursts of around a second". How to fix? There's a useful Serial Input Basics posting on the Arduino forum. That gives a few pointers. A good approach may be to receive your GPS speed data character by character and store it in a buffer as in Example 2 in the linked posting. Then you can parse the received buffer to get the speed value. As Rowan mentioned in an earlier post, if you can receive the speed as an integer value (rather than float), then the "atoi" function will convert the received buffer to an int value. [Edit] … and I've just found there is also an "atof" function that will convert a character string into a float - you could use that without having to mod the GPS sending code to send an int :-) Hope this helps! Good luck :-). -- Keith, Banchory Greenpower.
|
|
|
Post by Rowan on Jun 15, 2020 11:54:28 GMT
Edit: Gah - Keith beat me to it! I've been slowly writing this post in spare minutes through the morning I agree with him though - see below! Just going through your code, the serial read function is within the timed block for your CSV send, so is only being called when the CSV data is being sent every 2 seconds. Here's the block of code indented with some comments: if (millis() - lastCSVDataSendTime > CSV_DATA_TRANSMIT_INTERVAL)
{
lastCSVDataSendTime = millis();
char separator = ',';
mySerial.print(throttle), mySerial.write(separator); //Throttle
mySerial.print(batteryVoltageTotal), mySerial.write(separator); //Voltage
mySerial.print(currentAv), mySerial.write(separator); //Current
mySerial.print(SpeedMPH), mySerial.write(separator);//Motor rpm channel...in this version speed is output to rpm channel for rpm calculation
mySerial.print(SpeedMPH), mySerial.write(separator); //Speed in mph
mySerial.print(brake), mySerial.write(separator); //Brake
mySerial.print(motorTemp, 1), mySerial.write(separator); //Motor temperature
mySerial.print(mosfetTemp, 1), mySerial.println(); //MOSFET temperature
{ // Open bracket not doing anything if (mySerial.available() > 0) {
mySerial.read();
}
SpeedMPH = mySerial.parseFloat();
if (SpeedMPH < 1)
SpeedMPH = 0;
} // Closes the redundant open bracket above
} //ends the transmit interval status
Also on the serial read: if (mySerial.available() > 0) { mySerial.read(); }
SpeedMPH = mySerial.parseFloat();
The read function returns a value, so needs a 'char read_in_value = mySerial.read();' This is also removing the first character from the buffer before you read it in the next line. The ParseFloat line now takes in whatever's left in the serial buffer and tries to parse it to a float. If it can't it times out - which would cause a long delay likely similar to what you're seeing. What that should be is: (I haven't actually tested this at this point) if (millis() - lastCSVDataSendTime > CSV_DATA_TRANSMIT_INTERVAL)
{
lastCSVDataSendTime = millis();
char separator = ',';
mySerial.print(throttle), mySerial.write(separator); //Throttle
mySerial.print(batteryVoltageTotal), mySerial.write(separator); //Voltage
mySerial.print(currentAv), mySerial.write(separator); //Current
mySerial.print(SpeedMPH), mySerial.write(separator);//Motor rpm channel...in this version speed is output to rpm channel for rpm calculation
mySerial.print(SpeedMPH), mySerial.write(separator); //Speed in mph
mySerial.print(brake), mySerial.write(separator); //Brake
mySerial.print(motorTemp, 1), mySerial.write(separator); //Motor temperature
mySerial.print(mosfetTemp, 1), mySerial.println(); //MOSFET temperature
}
if (mySerial.available() > 0)
{
SpeedMPH = mySerial.parseFloat();
if (SpeedMPH < 1)
SpeedMPH = 0; }
Moving on to testing it, I added a little bit of code to measure the time spent both sending the CSV data and reading in the serial data: if (millis() - lastCSVDataSendTime > CSV_DATA_TRANSMIT_INTERVAL)
{
lastCSVDataSendTime = millis();
char separator = ',';
mySerial.print(throttle), mySerial.write(separator); //Throttle
mySerial.print(batteryVoltageTotal), mySerial.write(separator); //Voltage
mySerial.print(currentAv), mySerial.write(separator); //Current
mySerial.print(SpeedMPH), mySerial.write(separator);//Motor rpm channel...in this version speed is output to rpm channel for rpm calculation
mySerial.print(SpeedMPH), mySerial.write(separator); //Speed in mph
mySerial.print(brake), mySerial.write(separator); //Brake
mySerial.print(motorTemp, 1), mySerial.write(separator); //Motor temperature
mySerial.print(mosfetTemp, 1), mySerial.println(); //MOSFET temperature
long tmpSendTime = millis();
if(DEBUG_MODE){
Serial.print("CSV Send Time: ");
Serial.println(tmpSendTime - lastCSVDataSendTime);
}
long serialReadTime = millis();
{ if (mySerial.available() > 0) {
mySerial.read();
}
SpeedMPH = mySerial.parseFloat();
if (SpeedMPH < 1)
SpeedMPH = 0;
}
serialReadTime = millis() - serialReadTime;
if(DEBUG_MODE){
Serial.print("Serial Read Time: ");
Serial.println(serialReadTime);
}
} When running on the nano and watching on the serial monitor, this gives an output of: CSV Send Time: 44
Serial Read Time: 1000
CSV Send Time: 44
Serial Read Time: 1000
So, it's consistently taking 44ms to send all the CSV data out, which probably won't be an issue, but the serial read is timing out with a 1s timeout on the parseFloat function. Admittedly this isn't an amazing test as I've not got any data being sent to it yet, but I suspect this is the problem. Until I set up a second arduino to send the data out I can't do a proper test of the modified code above, but I suspect it will work - I've attached the .ino with the changes made if you want to try it John? XPOD120620_For_Rowan.ino (45.24 KB) PS. If you can increase the baud rate that you transmit the CSV data on to 115200, the transmit time drops to 4ms which definitely won't be an issue!
|
|
|
Post by Rowan on Jun 15, 2020 12:02:05 GMT
Actually slight amendment to the above. Checking if serial is available and then immediately trying to parse float in the main loop will likely catch each number you send individually - so 21.45 would be read out as 2.0, 1.0, 4.0, 5.0.
If you transmit the data with leading and trailing zeros, so 1mph would be sent as 01.00, you could use 'if(serial.available > 5)' as that would be when one complete variable is available.
|
|
|
Post by littlejo44 on Jun 15, 2020 12:14:02 GMT
Hi Keith and Rowan.. Wow..Many thanks both!! I’m in Basingstoke at present, so (frustratingly) can’t try anything at the moment😩..But I’m humbled by the fact that you guys have taken the time to try and help me out here.. so, again, I’m in your debt.. I’ll be home tomorrow, so I’ll have a look on the ‘big screen’ and see if I can get something to compile ☹️..That seems to be (as an obvious novice) my biggest problem...understanding the errors that IDE throws at me when I try and edit a sketch..Sometimes that learning curve becomes vertical ☹️☹️ Thanks again, and I’ll get back when I’ve had a chance to upset my school again. John
|
|
|
Post by littlejo44 on Jun 15, 2020 13:05:34 GMT
....that last sentence should have read ...'when I've had a chance to upset my ECHOOK again'😊
|
|
|
Post by Rowan on Jun 15, 2020 13:28:11 GMT
I did wonder!
|
|
|
Post by littlejo44 on Jun 18, 2020 6:40:08 GMT
Hi Rowan/Keith.. Well...I gave it a try, sending from the gps with leading and trailing zeros, as suggested, and set the echook to look for >5 characters.. ...but as soon as the gps data started arriving, the 2 second Transmit period started to fluctuate randomly between two and four seconds, and the throttle ramp no longer functioned correctly...
Despite the erratic operation, the gps data imported correctly, and in turn, arrived correctly integrated, at the telemetry receiver ok..along with all the other parameters...but, as there is no real throttle control, I'm thinking now that my gps idea is just not going to work...I'm amazed at what a dramatic difference just importing a few characters every couple of seconds, can make!..
I could try increasing the baud rate, but in practice, I would also have to access our other car, when it's possible, to reprogram the controller and transmitter to comply, and, as it still might not work, perhaps I should just use the time to fit the magnets to the wheel, ( which we would have done if it wasn't for that virus!)
You guys have already spent a lot of time looking at this for me, and I've learnt a lot from this exercise, so my thanks for that, but do you agree it's time for a rethink? John
|
|
|
Post by keduro on Jun 18, 2020 7:02:27 GMT
Good morning John. If you'd like to post your latest code I'll be happy to take another look. I don't like being beaten by an Arduino! It should be possible to make it work. Can you also provide the exact format of what your GPS nano is sending and the echook is receiving, e.g. something like " 08.90 011.70 012.50 012.40 010.90" and particularly if there is anything other than spaces between successive values. I'm still suspicious that parseFloat may be blocking the code execution and causing the behavior you are seeing. -- Keith
|
|
|
Post by Rowan on Jun 18, 2020 8:05:59 GMT
I'll echo what Keith has said!
If you comment out my timing code you should be able to watch the serial monitor and see where the delays are.
|
|
|
Post by littlejo44 on Jun 18, 2020 10:32:13 GMT
Hello again Wow!...and I thought you'd both be relieved😄.. To be clear, although my old brain struggles with it, I am totally addicted to learning 'things Arduino', but, as I expect you can sense, I'm starting to panic here....Circumstances here dictate that my 'echook time', even with this lockdown, is limited, and I have parts of a car controller spread around my garage with 'life support' cables linking everything together. I'm sure you guys are familiar with the scenario😊...and I need to squash this collection of parts into a box by the time the rest of the team arrive on my doorstep with the car😩.. My 'quick fix' turned out not to be so quick, so I'm panicking... However...I digress.. Keith, in response to your question, I am using the code that Rowan published on June 15th at 12.54.. and all the gps is sending to the echook ss input is the mph parameter in the form of (say) 01.50 Just 5 characters..every 2 seconds.. Thanks for your support, gents.. John
|
|
|
Post by littlejo44 on Jun 18, 2020 11:16:45 GMT
Patio!!...you need to sort out your priorities!!😊
|
|
|
Post by keduro on Jun 18, 2020 16:00:36 GMT
Hi John … have downloaded Rowan's updated code and looking at it now. Just sending this message so that both Rowan and I aren't working it at the same time :-). I'm pretty sure that parseFloat is still causing the problem. Even if the code checks for > 5 (though I suspect that should have been >= 5) characters available, parseFloat will still block after consuming those 5 characters waiting for either another character that could be part of the number, or the 1s timeout. With GPS data coming every 2s then it will timeout. But the code is blocked, i.e. nothing else will run, until the timeout happens.
I will put together a quick sketch to emulate your GPS nano on another board and feed that to a nano running your code. I hope to confirm the above hypothesis by looking at the timings from the code that Rowan added. Assuming I'm on the right track I'll rewrite the GPS receiving bit of code to be non-blocking by reading in a character at a time. Once no characters have been received for say 1s I will then convert the received characters to a float and assign to SpeedMPH.
Will keep you posted as to what I find and hopefully we can get something working that you can use :-).
More later …………………. Keith
|
|