The Homebuilt Dynamometer (Dyno)Thread!!!
#121
I agree that a 10Hz sample rate doesn't indicate which way it works. My friend bought their dyno several years ago and was able to determine that it was counting ticks instead of time between ticks. He wrote the company to convince them that the data was pretty bad because of this mode of measurement. They weren't willing to work with him on a fix at that time.
Are you dead set on using the R4? Is it the 5V you are trying to stick to? Honestly I think the easiest way to go would be to use an ESP32 with an external ADC, like the ADS 1015 or mcp3204 if you want SPI. You can get those current sensors in the 773 which are 3.3V. Then you can get the Arduino ESP32 and pretty much port your code to it with the same footprint you have now. With the exception of the ADC, which is horrible on the ESP32.
#122
Well that is frustrating... I guess it makes sense why you get seismographs at higher sample rates.
Are you dead set on using the R4? Is it the 5V you are trying to stick to? Honestly I think the easiest way to go would be to use an ESP32 with an external ADC, like the ADS 1015 or mcp3204 if you want SPI. You can get those current sensors in the 773 which are 3.3V. Then you can get the Arduino ESP32 and pretty much port your code to it with the same footprint you have now. With the exception of the ADC, which is horrible on the ESP32.
Are you dead set on using the R4? Is it the 5V you are trying to stick to? Honestly I think the easiest way to go would be to use an ESP32 with an external ADC, like the ADS 1015 or mcp3204 if you want SPI. You can get those current sensors in the 773 which are 3.3V. Then you can get the Arduino ESP32 and pretty much port your code to it with the same footprint you have now. With the exception of the ADC, which is horrible on the ESP32.
#123
Nope, I am open to ideas on how to do it best. I am not the best programmer in C. I prefer doing stuff with FPGA's but that makes communication with the outside world harder. Will using a SPI ADC interfere with using interrupts to measure RPM? Don't they both want to use interrupts?
Out of curiosity, did you try lowering your baud rate for the serial connection when streaming the serial data simultaneously? I know a lot of people default to 112500, 9600 is slower by may not interfere as much.
#124
I'm not sure if the SPI uses interrupts, but it shouldn't be an issue. Most of them have a library, or you can bit bang them, which is what I default to. Using the ESP32, I think the clock is 80MHz and if the SPI hardware uses interrupts it isn't using the interrupt pins. Which on an ESP32 is most of them.
Out of curiosity, did you try lowering your baud rate for the serial connection when streaming the serial data simultaneously? I know a lot of people default to 112500, 9600 is slower by may not interfere as much.
Out of curiosity, did you try lowering your baud rate for the serial connection when streaming the serial data simultaneously? I know a lot of people default to 112500, 9600 is slower by may not interfere as much.
#125
But, doesn't matter if you are storing everything in an array and sending it later. Just takes up space.
To be honest, your curves look good, really smooth. So long as they are repeatable, everything else can be sorted out by the mcu choice and peripherals you decide to go with.
EDIT: SPI does not use interrupts, but I2C does.
#126
That would make your ISR take longer. Goal of the ISR, get in set a flag, make timestamp, etcetera, and get out. Leave everything else outside the ISR and use millis or micros to facilitate your sample rates. That way your ISR can interrupt your serial communication and your serial communication shouldn't hurt your ISR since you'll be doing it when the ISR is not happening.
But, doesn't matter if you are storing everything in an array and sending it later. Just takes up space.
To be honest, your curves look good, really smooth. So long as they are repeatable, everything else can be sorted out by the mcu choice and peripherals you decide to go with.
EDIT: SPI does not use interrupts, but I2C does.
But, doesn't matter if you are storing everything in an array and sending it later. Just takes up space.
To be honest, your curves look good, really smooth. So long as they are repeatable, everything else can be sorted out by the mcu choice and peripherals you decide to go with.
EDIT: SPI does not use interrupts, but I2C does.
#127
Yes, the curve I posted is a good curve but it isn't the way the SimpleDyno software measures it. Also, it is a fairly short set of data due to the limited ram. Since I only use the Arduino IDE for programming, the chip manufacturer makes no difference to me. I think it is possible to trick the SD software to accept a file made from my array setup but I haven't done it yet. Since the Minima has 16x the memory, I should be able to get a full set of data with RPM, voltage and current. Still messing around with different ideas which is what makes it fun!
#128
I'm happy to contribute what I can to this. For example, I've got a datalogging board that captures a bunch of stuff at 50Hz and writes it to a microSD card as it goes, so it can record practically forever (well, not really, but in RC terms, I've captured whole runs at 50Hz. Current version of the hardware captures battery voltage, motor RPM, throttle input and acceleration in 3 axes.
#129
I'm happy to contribute what I can to this. For example, I've got a datalogging board that captures a bunch of stuff at 50Hz and writes it to a microSD card as it goes, so it can record practically forever (well, not really, but in RC terms, I've captured whole runs at 50Hz. Current version of the hardware captures battery voltage, motor RPM, throttle input and acceleration in 3 axes.
#130
EDIT: I could be wrong, but that seems like the direction to try and take.
#131
The current design captures only one sensor from the motor (ie: one revolution), but could be extended to look at all three. It would work by measuring time between pulses and can be accurate down to CPU clock rate (eg: 1/20th microsecond). Sometimes need to be careful if the rate is too low, because you can get overflow, but there are tricks for dealing with that.
#133
I did a bit more testing on the number of pickups for the RPM measurement. I think the noise comes from two things. 1-The holes in the disk are not perfectly 90 degrees apart. 2-The jitter in the interrupt command on the Arduino Nano is about 10 to 20 usec.
I was able to look at the RPM measurement with my scope and I can see that there is jitter. If I trigger the scope on the rising edge of a pickup, I can see the next 3 pickups jitter in time but the 4th (which is the first one again) is perfectly still. It isn't hard to believe that the disk isn't perfect. It is only 3d printed and I had to put tape over it to make it work (PLA is tranparent to infrared light). I then had to use an Xacto to cut out the holes again. I am sure there is some slot in the dimensions.
The interrupt jitter in the Arduino is another problem. I want at least 4 pickups per revolution so that the low RPM data is captured but that makes it harder for the Arduino to time accurately. If you only use 1 pickup, you will get redundant measurements (i.e. if measurements are taken every 20msec and you are lower than 3000rpm, you will get two identical data points). This can be seen in the power curve for the 1 hole disk. 4 holes seems to be the best but the rpm gets pretty sloppy at higher RPM's. The plots below at 4 holes, 2 holes and 1 hole respectively.



I was able to look at the RPM measurement with my scope and I can see that there is jitter. If I trigger the scope on the rising edge of a pickup, I can see the next 3 pickups jitter in time but the 4th (which is the first one again) is perfectly still. It isn't hard to believe that the disk isn't perfect. It is only 3d printed and I had to put tape over it to make it work (PLA is tranparent to infrared light). I then had to use an Xacto to cut out the holes again. I am sure there is some slot in the dimensions.
The interrupt jitter in the Arduino is another problem. I want at least 4 pickups per revolution so that the low RPM data is captured but that makes it harder for the Arduino to time accurately. If you only use 1 pickup, you will get redundant measurements (i.e. if measurements are taken every 20msec and you are lower than 3000rpm, you will get two identical data points). This can be seen in the power curve for the 1 hole disk. 4 holes seems to be the best but the rpm gets pretty sloppy at higher RPM's. The plots below at 4 holes, 2 holes and 1 hole respectively.



#135
By the way, here is the sketch for the Arduino.
//
//
/*
Sketch for use with SimpleDyno
Developed on Arduino Uno Platform
DamoRC - 2013-2014
ALWAYS use the Sketch distributed with each new version of SimpleDyno
Transmits:
1 x Session timestamp
1 x Interrupt timestamp and 1 x time interval since last interrupt for INT0 / Pin2 / RPM1
1 x Interrupt timestamp and 1 x time interval since last interrupt for INT1 / Pin3 / RPM2
6 x Analog Inputs (A0 and A1 are Voltage and Current, A2 and A3 are Temperature, A4 and A5 are open)
Values are comma delimeted
Baud rates selected in SD must match coded values in this Sketch.
*/
const int NumPortsToRead = 6;
int AnalogResult[NumPortsToRead];
volatile unsigned long TimeStamp = 0;
volatile unsigned long time1 = 0;
volatile unsigned long time2 = 0;
volatile unsigned long Oldtime1 = 0;
volatile unsigned long Oldtime2 = 0;
volatile unsigned long TempTime1 = 0;
volatile unsigned long TempTime2 = 0;
String AllResult = "";
void setup() {
// Initialize serial communication
// Ensure that Baud rate specified here matches that selected in SimpleDyno
// Availailable Baud rates are:
// 9600, 14400, 19200, 28800, 38400, 57600, 115200
Serial.begin(115200);
// Initialize interupts (Pin2 is interrupt 0 = RPM1, Pin3 in interrupt 1 = RPM2)
attachInterrupt(0,channel1,FALLING);
// attachInterrupt(1,channel2,FALLING);
}
void loop() {
AllResult = "";
AllResult += micros();
AllResult += ",";
AllResult += TempTime1;
AllResult += ",";
AllResult += time1;
AllResult += ",";
AllResult += TempTime2;
AllResult += ",";
AllResult += time2;
for (int Looper = 0; Looper < NumPortsToRead;Looper++){
AnalogResult[Looper] = analogRead(Looper);
AllResult += ",";
AllResult += AnalogResult[Looper];
}
Serial.println (AllResult);
Serial.flush();
delay(20); //20 is default
}
//Interrupt routine for RPM1
void channel1(){
TempTime1 = micros();
time1 = TempTime1-Oldtime1;
Oldtime1 = TempTime1;
}
//Interrupt routine for RPM2
//void channel2(){
// TempTime2 = micros();
// time2 = TempTime2-Oldtime2;
// Oldtime2 = TempTime2;
//}
//
//
/*
Sketch for use with SimpleDyno
Developed on Arduino Uno Platform
DamoRC - 2013-2014
ALWAYS use the Sketch distributed with each new version of SimpleDyno
Transmits:
1 x Session timestamp
1 x Interrupt timestamp and 1 x time interval since last interrupt for INT0 / Pin2 / RPM1
1 x Interrupt timestamp and 1 x time interval since last interrupt for INT1 / Pin3 / RPM2
6 x Analog Inputs (A0 and A1 are Voltage and Current, A2 and A3 are Temperature, A4 and A5 are open)
Values are comma delimeted
Baud rates selected in SD must match coded values in this Sketch.
*/
const int NumPortsToRead = 6;
int AnalogResult[NumPortsToRead];
volatile unsigned long TimeStamp = 0;
volatile unsigned long time1 = 0;
volatile unsigned long time2 = 0;
volatile unsigned long Oldtime1 = 0;
volatile unsigned long Oldtime2 = 0;
volatile unsigned long TempTime1 = 0;
volatile unsigned long TempTime2 = 0;
String AllResult = "";
void setup() {
// Initialize serial communication
// Ensure that Baud rate specified here matches that selected in SimpleDyno
// Availailable Baud rates are:
// 9600, 14400, 19200, 28800, 38400, 57600, 115200
Serial.begin(115200);
// Initialize interupts (Pin2 is interrupt 0 = RPM1, Pin3 in interrupt 1 = RPM2)
attachInterrupt(0,channel1,FALLING);
// attachInterrupt(1,channel2,FALLING);
}
void loop() {
AllResult = "";
AllResult += micros();
AllResult += ",";
AllResult += TempTime1;
AllResult += ",";
AllResult += time1;
AllResult += ",";
AllResult += TempTime2;
AllResult += ",";
AllResult += time2;
for (int Looper = 0; Looper < NumPortsToRead;Looper++){
AnalogResult[Looper] = analogRead(Looper);
AllResult += ",";
AllResult += AnalogResult[Looper];
}
Serial.println (AllResult);
Serial.flush();
delay(20); //20 is default
}
//Interrupt routine for RPM1
void channel1(){
TempTime1 = micros();
time1 = TempTime1-Oldtime1;
Oldtime1 = TempTime1;
}
//Interrupt routine for RPM2
//void channel2(){
// TempTime2 = micros();
// time2 = TempTime2-Oldtime2;
// Oldtime2 = TempTime2;
//}



16Likes
