Motorcycle Data Logger: Counting Digital Pulses From Three Sensors?

Hi All,

I'm building a data logger for my motorcycle and this is my first real foray into electronics. What I currently have is a Uno R3 with a4 digit 7segment display and two neopixel sticks for displaying the tach and settings. Currently I'm sensing the RPM's with a ?RC low pass filter? directly from the ignition circuit to an interrupt that increments a counter I read and rest in the loop and it works great.

Now, I'm adding a gyroscope/accell breakout board, GPS(I'd like to read the gps at 10Hz), and SD card to log the data from the sensors to. Using all of the examples, I tested everything and they all work independently.

As you can guess, I'm out of sram. While I wait on a mega (tried pairing down the libs, made progress but not enough. the sd / gps shield example took up ~1800 bytes before I added anything else; that is a realllly poor starting point and my C++ is nothing to write home about) I'm planning my next steps. I would like to use hall effect sensors to count RPM's on each wheel to calculate slippage, and allow me to calculate what gear I'm in by combining RPM and wheelspeed. The hall sensors should be ~16Hz max(18inch radius, top speed <100mph). In addition I would like to add throttle and brake position sensors (two brake sensors one front and one rear). I'm not sure how to do this yet but I'm thinking some type of potentiometer for an analog signal.

Now that you have my context, my problem:
I need to count pulses from three inputs, rpm, front wheel hall, rear wheel hall.

My tentative solution is to take three shift registers(sensor buffers), attach all of their outputs to one shift register in reverse(ardy interface), tell the buffer register to dump it's contents to the latch on the shift registery setup in reverse that is doing a parallel read, then read the signal pin of that shift register to get the count, reset everything, move to the next sensor lather, rinse repeat. Am I overlooking a simpler solution? It seems like doing a digital, read on something that just counts digital input pulses shouldn't be this difficult to offload?

Assuming I can completely quit using interupts, and rely using the GPS in soft serial to buffer it's output (big question). The pseduo code for my loop would look something like this:

void loop(){
	//currently my dataLoopInterval is 10ms, this may not work with the write to the SD + all the reads
	//as long as this takes less than 100ms, it should be fine I'll adjust it to a multiple of 100 as needed
	//this method could also drift, should I use a timer interupt?
	if(currentTime >= (loopTime + dataLoopInterval )){ //10ms

		//update the rolling average of the last 25 ticks with however rpms happened in the last ~10ms tick
		updateRpm();

		if (GPS.newNMEAreceived()) char *gpsSentence = readGps();

		lsm.read(); // put the most recent gyro / accel data from their respective buffers into properties

		//accel info
		int ax = lsm.accelData.x;
		int ay = lsm.accelData.y;
		int az = lsm.accelData.z;

		//lean angle info
		int gx = lsm.gyroData.x;
		int gy = lsm.gyroData.y;
		int gz = lsm.gyroData.z;

		//frontWheel a digital pin connected to the shift reg buffering the rear wheel
		byte fw = shiftRegRead(frontWheel); 

		//rearWheel a digital pin connected to the shift reg buffering the front wheel
		byte rw = shiftRegRead(rearWheel);

		logData(gpsSentence, rpm, gx, gy, gz, ax, ay, az, rw, fw); //save it all to the SD; rpm is a global
		loopTime = currentTime;
	}
	//every 100ms write the current RPM's out to the displays
	if(currentTime >= (displayTime + renderLoopInterval)){ //100ms
		writeLightBar();
	    writeSegDisplay();
	    displayTime = currentTime;
	}
}

Sorry for a wall of text and thank you for taking the time to read this far if you made it! If you have any feedback about the approach I'd apprecate it! (Even if it is have you googled xyz? I don't know what I'm missing)

From that brief snippit of code, there's really not much we can say. I did notice, however, that you are not following the standard practice of using SUBTRACTION in your time calculations.

This article explains the issue pretty well.

Thanks for the info on subtraction, because of my app it shouldn't cause a problem, but I'll switch it just to get in the habit.

I guess the crux of my question isn't about the code, I only included it to demo my thoughts on reading all the sensors. Maybe I should have made it more clear but my question is really this section:

hackdo:
I need to count pulses from three inputs, rpm, front wheel hall, rear wheel hall.

My tentative solution is to take three shift registers(sensor buffers), attach all of their outputs to one shift register in reverse(ardy interface), tell the buffer register to dump it's contents to the latch on the shift registery setup in reverse that is doing a parallel read, then read the signal pin of that shift register to get the count, reset everything, move to the next sensor lather, rinse repeat. Am I overlooking a simpler solution? It seems like doing a digital, read on something that just counts digital input pulses shouldn't be this difficult to offload?

Thanks!

So it looks like my understanding of interrupts were flawed. The interrupt waiting flag, would get set and my waiting interrupt handlers would get called after the currently executing interrupt finished. The only gotcha's are you need to service the interrupt before it gets called again, because that would lead to loss of sensing. Second if you are updating anything in your interrupt that that is larger than a byte, make sure you turn off interrupts, create a local copy of the variable, then turn interrupts back on before you read it. If the an interrupt lands in the middle of a multi-clock cycle read bad things can happen.

hackdo:
if you are updating anything in your interrupt that that is larger than a byte, make sure you turn off interrupts, create a local copy of the variable, then turn interrupts back on before you read it.

I think you've missed the point of volatile variables.

Yep, I missed that too. It is almost like this is my first project and I'm posting in a guidance forum :wink:

KenF:
I think you've missed the point of volatile variables.

I think Hackdo was right. To sensibly read a multi-byte variable which is updated by interrupts, you need to snag a copy of it while interrupts are disabled. Writing it however, doesn't require disabling interrupts unless your program is so poorly planned that two different threads/processes/ISRs are competing to write to a variable.

I don't quite understand the original question or even if there is is a question. Hackdo seems to be proposing using single-chip shift registers to count signals so that the Arduino doesn't have to run an ISR for every single pulse of the input. 3 ISRs at those kinds of frequencies (16Hz is a typo) may not be possible on an Arduino, particularly if you want to do other stuff in between.

Why not use a counter? I haven't looked but I'm sure binary counter chips still exist. Set it up as a divider - just connect the 3rd output to the Arduino's interrupt input and you will get an interrupt on every eighth input pulse. By clever connection of the counter's outputs to its reset line, you can divide by any number, not just powers of 2. Google counter divider.

I was looking for a sanity check, the shift registers or better yet counters as you suggest works. But I realized I was putting in a ton of effort to find a solution to a problem, that seemed very generic and very common, counting digital pulses. AKA it is time to ask for help.

Turns out that the problem is as simple as it seems, because interrupt service flags get set, not interrupts missed. So digital counting for an ardy is as simple as doing a sensorCounter++; in your interrupt. Hope that clears up what I came up with!

Sanity check complete. You pass :slight_smile: My ignorance of "volatile" almost cost me mine when I started playing with the arduino.