So, this is pretty much where I stand. I know, not aesthetically too impressive but a) it isn't connected to my car/V1, and b) it's just for my debugging purposes right now.
Trapster has respectfully (but officially) indicated that they are not interested in supporting autonomous reporting through this project in any way, so we're/I'm pretty much on my own in that respect.
I'll work on finalizing the remote display stuff, optimizing the most efficient and cheap way for people to build these with "off the shelf" parts, write up a little "how-to" guide, and finish coding up the remote display app so that it is usable for background/driving purposes. I have a big nasty (and important) controls theory midterm this Thursday, and then I start spring break and head to the beach/key west so I doubt I'll get too much work done during then... lo siento!
For now those of you waiting patiently will have to deal with these snippets of code and a single pic:
Code:
/*---------------------------------\
| V1 Stream to Bluetooth |
| Copyright (c) 2010: Nate Weibley |
| |
| If you use or modify this code |
| in your own projects I ask only |
| that you offer attribution to |
| the original authors and code. |
| |
\---------------------------------*/
//Command stream start bit duration (tolerances)
#define SYNC_BIT_MINL 10500
#define SYNC_BIT_MAXL 12000
// I/O Pins
unsigned int commandPIN = 5;
unsigned int mutePIN = 8; //TODO: implement mute control prot.
unsigned int commandStream[35]; //Stream storage array
unsigned int i=0; //Indexing variable
unsigned long pulseLen=0; //Pulse length
void setup() {
Serial.begin(57600); //NOTE: I set BT chip to 57600 baud. Default is 2x
pinMode(commandPIN, INPUT);
pinMode(mutePIN, OUTPUT);
digitalWrite(mutePIN, LOW);
}
void loop() {
waitForV1stream();
//It's go time.
pulseIn(commandPIN, HIGH); //Skip the start bit, it is irrelevant.
//Read the next 35 bits
for(i=0; i<34; i++) {
//Check the pulse length of the bit
int len = pulseIn(commandPIN, HIGH);
//If the length is over 240microseconds, the bit is a 1
if(len > 240) commandStream[i] = HIGH;
//Otherwise it is a 0
else if(len < 240) commandStream[i] = LOW;
}
//Transmit the frame through the bluetooth modem
sendFrame();
}
void sendFrame() {
//Give the software the frame start pattern
Serial.write("$FRAMESTART$");
//Send the first bit
Serial.print(commandStream[0]);
//Send the rest of the bit sequence
for(i=1; i<34; i++) {
Serial.write(",");
Serial.print(commandStream[i]);
}
//Give the software the frame end pattern
Serial.write("$FRAMEEND$");
}
void sendDisconnected() {
//The V1 is offline. Bad news, tell the software.
Serial.write("$FRAMESTART$$NODETECT$$FRAMEEND$");
}
void waitForV1stream() {
//Loop endlessly waiting for the command stream start sync pulse
while(true) {
//Listen for a command stream start sync pulse
pulseLen = pulseInMax(commandPIN, HIGH, 1*1000000, 1*1000000);
//Check if pulse length matched start bit
if(pulseLen >= SYNC_BIT_MINL && pulseLen <= SYNC_BIT_MAXL) return;
//It didn't. Is the pulse driven high? If so the V1 is off and/or not signaling.
if(pulseLen >= 500000 || pulseLen == 0) {
//Is this the 3rd off state?
if( i >= 3 ) {
//It is. Report the V1's off state over bluetooth again.
sendDisconnected();
i=0;
} else
//Increment state counter
i++;
}
}
}
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
Also, the following function needs to be added to the arduino library file wiring_pulse.c
Code:
unsigned long pulseInMax(uint8_t pin, uint8_t state, unsigned long timeout, unsigned long maxlen)
{
//NOTE: This modified function clamps pulseIn to a max time. -Nate
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 16 clock cycles per iteration.
unsigned long numloops = 0;
unsigned long pulseloops = 0;
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
unsigned long maxtimeloops = microsecondsToClockCycles(maxlen) /16;
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask)
if (pulseloops++ == maxtimeloops)
return 0;
// convert the reading to microseconds. The loop has been determined
// to be 10 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
//NOTE: From estimations adding the conditional check adds 6 cycles
// thus "fudge factor" upped to 16.
return clockCyclesToMicroseconds(pulseloops * 16 + 16);
}
And to wiring.h (in the same directory... ./hardware/cores/arduino/)
Code:
unsigned long pulseInMax(uint8_t pin, uint8_t state, unsigned long timeout, unsigned long maxlen); //added by nate

Obligatory Gator backdrop included. GO GATORS!