/* JPEG Trigger - Default Code Written by Ryan Owens SparkFun Electronics The new JPEG Trigger is designed to interface with the LinkSprite JPEG Color Camera TTL Interface (SEN-10061). The board has an Arduino Compatible AtMega328 (Similar to Arduino 5V/16Mhz w/ AtMega328) and a microSD socket for storing pictures. There are mounting holes on the PCB which will allow the camera to be mounted directly on top of the board. The device can be powered by an input voltage of 1-4V DC; the JST connector will allow you to use a single-cell Lithium Polymer battery. There is also a bank of headers which allow access to the software 'triggers.' Be careful using these headers as they also include the 5V and GND rails. The I/O pins are actually the pins which run along the edge of the board. The default firmware requires that a FAT16 formatted microoSD card be inserted into the microSD socket. After the JPEG Trigger is powered on, the status LED will turn on signifying the board is in the READY state, and the board is ready to be triggered. If the LED starts blinking, the SD card failed to initialize and you should make sure it's been formatted correctly. When the board is in the READY state, the camera can be triggered by: A.) Pulling pins D2,D3 or D4 to ground B.) Pulling pins A0, A1 or A2 to 5V. Once the camera is triggered the board will go into the RECORDING state. The camera will capture a JPEG image and save it to the SD card. The file will be saved with a simple 3 digit number. The file names increment each time a picture is captured. While recording, the status LED will start blinking. The camera can not be triggered again until the board finishes recording the current picture. After the JPEG Trigger has finished recording the image, the board will go back into the READY state and the status LED will go back to being solid. The file recorded by the JPEG Trigger is actually saved as a '.txt' file on the SD card. To retrieve the image you must remove the SD card from the device and copy it onto a computer. Once you've copied the image to the computer, rename the file so that it has the extension '.jpg' and you will be able to view the images. Hardware Notes: When connecting the LinkSprite Camera to the JPEG Trigger board, make sure to plug Rx on the camera into D6(Tx) of the JPEG Trigger, and Tx on the camera to D5(Rx) of the JPEG Trigger. 5V should be connected to Vcc of the camera, and GND should be shared. */ //This example requires the MemoryCard, SdFat, JPEGCamera and NewSoftSerial libraries #include #include #include #include #include //Create an instance of the camera JPEGCamera camera; //Create a character array to store the cameras response to commands char response[32]; //Count is used to store the number of characters in the response string. unsigned int count=0; //Size will be set to the size of the jpeg image. int size=0; //This will keep track of the data address being read from the camera int address=0; //eof is a flag for the sketch to determine when the end of a file is detected //while reading the file data from the camera. int eof=0; char fileName[32]; int fileNumber=0; char triggerNumber[3]; //The Status LED is on digital pin 18 (Analog pin 4) char ledPin=18; //There are 3 system statuses, READY, NOT_READY, and PROCESSING char NOT_READY=0; char READY=1; char PROCESSING=2; //Create a variable to keep track of the status and set it to 'Ready' by default char systemStatus=NOT_READY; int timeout=0; void setup() { //Setup the camera, serial port and memory card camera.begin(); Serial.begin(9600); //Set the LED as an output pinMode(ledPin, OUTPUT); //Set up a timer interrupt which will control the LED. Update it every 1/10 of a second Timer1.initialize(100000); Timer1.attachInterrupt(updateStatusLed); //Configure the digital I/O pins as inputs pinMode(2, INPUT); pinMode(3, INPUT); pinMode(4, INPUT); //Set the pull-up resistor on the inputs. digitalWrite(2, HIGH); digitalWrite(3, HIGH); digitalWrite(4, HIGH); //Check to see if we need to go into test mode timeout = millis(); while(millis() < timeout + 1000) { //If we get a character, check to see if it's the 'start testing' character if(Serial.available() > 0) { //Run the test procedure if we get the 'start testing' character if(Serial.read() == 'T') { //Send a response character to the test jig to indicate we're starting testing delay(10); Serial.print('T'); systemStatus=PROCESSING; delay(100); //Try initializing the SD card if(MemoryCard.begin()){ //If the card initializes, send a '1' indicating success. Serial.print('P'); systemStatus = READY; } else{ //If the card fails to initialize, send a '0' to indicate failure. Serial.print('F'); } /* //Now test the I/O Pins //All the I/O are pulled low by the test jig. So if any of them read high, there's a failure. if((digitalRead(2)==HIGH)||(digitalRead(3)==HIGH)||(digitalRead(4)==HIGH) ||(digitalRead(14)==HIGH)||(digitalRead(15)==HIGH)||(digitalRead(16)==HIGH) ||(digitalRead(xx)==HIGH)||(digitalRead(xx)==HIGH)){ Serial.print(0x00, BIN); //Indicate there was an I/O failure while(1); } //Now set a pin in one of the groups high. Make sure this group all goes high and the other group all goes low. //If this fails, send the fail command. pinMode(2, OUTPUT); digitalWrite(2, HIGH); if((digitalRead(2)==LOW)||(digitalRead(4)==LOW)||(digitalRead(6)==LOW)||(digitalRead(14)==LOW)||(digitalRead(16)==LOW) ||(digitalRead(3)==HIGH)||(digitalRead(5)==HIGH)||(digitalRead(15)==HIGH)){ Serial.print(0x00, BIN); //Indicate there was an I/O failure. while(1); } //Repeat the last test, but with a pin in the other group high. pinMode(2, INPUT); pinMode(3, OUTPUT); digitalWrite(3, HIGH); if((digitalRead(2)==HIGH)||(digitalRead(4)==HIGH)||(digitalRead(6)==HIGH)||(digitalRead(14)==HIGH)||(digitalRead(16)==HIGH) ||(digitalRead(3)==LOW)||(digitalRead(5)==LOW)||(digitalRead(15)==LOW)){ Serial.print(0x00, BIN); //Indicate there was an I/O failure. while(1); } //If we make it here, then the I/O test has passed. Serial.print(0x01, BIN); */ //The test is over; wait for a reset. //systemStatus=READY; delay(1); while(1); } } } //Initialize the SD Card //If the card initialization fails, blink the LED and stop the program if(!(MemoryCard.begin())){ systemStatus=PROCESSING; Serial.println(systemStatus); while(1); } //Reset the camera count=camera.reset(response); delay(1000); } void loop() { systemStatus=READY; delay(500); //Wait until one of the inputs causes a trigger. while(!cameraTriggered(triggerNumber)); //Change the system status to indicate we're taking a picture. systemStatus=PROCESSING; recordPicture(triggerNumber); //Reset the camera count=camera.reset(response); } void updateStatusLed(void) { //If the status is 'Ready' turn the LED on if(systemStatus==READY)digitalWrite(ledPin, HIGH); //If status is 'Not Ready' turn the LED off else if(systemStatus==NOT_READY)digitalWrite(ledPin, LOW); //If the status is 'Taking Picture' blink the LED. else if(systemStatus==PROCESSING){ PINC |= (1<<4); } } char cameraTriggered(char * triggerType) { //Create a variable that will indicate if the camera has been triggered. char triggered=0; //Find out if any of the digital inputs have been triggered. if(digitalRead(2)==LOW){ sprintf(triggerType, "D2"); triggered=1; } else if(digitalRead(3)==LOW){ sprintf(triggerType, "D3"); triggered=1; } else if(digitalRead(4)==LOW){ sprintf(triggerType, "D4"); triggered=1; } //if((digitalRead(2)==LOW)||(digitalRead(3)==LOW)||(digitalRead(4)==LOW))triggered=1; //Find out if any of the analog inputs have been triggered. else if(analogRead(0) > 950){ sprintf(triggerType, "A0"); triggered=1; } else if(analogRead(1) > 950){ sprintf(triggerType, "A1"); triggered=1; } else if(analogRead(2) > 950){ sprintf(triggerType, "A2"); triggered=1; } //if((analogRead(0) > 950) || (analogRead(1) > 950) || (analogRead(2) > 950))triggered=1; return triggered; } void recordPicture(char * filePrefix) { //Take a picture count=camera.takePicture(response); //Get the size of the picture so we know how much data to read. count = camera.getSize(response, &size); //Create a new file name. Start with 'trigger-000.jpg' and increment the number until we find a filename that doesn't exist yet. sprintf(fileName, "/%s-%03i.jpg", filePrefix, fileNumber); while(MemoryCard.exists(fileName)){ fileNumber+=1; sprintf(fileName, "/%03i.jpg", fileNumber); } //Create a new file with the file name we found. MemoryCard.open(fileName, true); //Starting at address 0, keep reading data until we've read 'size' data from the camera. address=0; eof=0; while(address < size) { //Read the data starting at the current address. count=camera.readData(response, address); //Store all of the data that we read to the SD card for(int i=0; i