diff --git a/README.md b/README.md index 15beae0..1c983aa 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,8 @@ This super simple win32 example shows how draw the images onto the screen of a w edison_capture -------------- This example shows how to capture a still image from the lepton using Intel Edison. + +MbedLPC1768Lepton +-------------- +This example uses the Mbed frame work to read from the Lepton camera. The example uses the LPC1768, though any mbed with the correct hardware, spi and usb serial out, will work. This implementation will send at 5FPS. Suggested improvement would use the DMA available on the mbed (platform dependant) to allow parralel reading fromt the Lepton and sending to the PC, this should achieve the max 9FPS. +There is also a python script that reads this, the image is headed with 0xDEADBEEF like the stm32nucleo version. The image is presented as a colour mapped image where the min and max colour can be changed by clicking with the right and left mouse buttons on the points of interest in the image. The image is upscaled for visability, and an FPS readout is given. diff --git a/software/MbedLPC1768/LeptonRead.py b/software/MbedLPC1768/LeptonRead.py new file mode 100644 index 0000000..0bbb993 --- /dev/null +++ b/software/MbedLPC1768/LeptonRead.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +#Copyright (c) 2015, Josh Elsdon + +#Redistribution and use in source and binary forms, with or without +#modification, are permitted provided that the following conditions are met: +#* Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +#* Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# this code will read from the mbed the Lepton thermal image. It will then display +# the image using a colour mapping, use right and left click on the image to change +# the min and the max values of the mapping. + + +import serial +import cv2 +import sys +import numpy +from collections import namedtuple +import struct +import time + + +def unsigned(n): + return n & 0xFFFFFFFF + +min = 8050 +max = 8650 +xloc = 0 +yloc = 0 +newRclick = 0 +newLclick = 0 + + +def onMouse(event,x,y,flags,param): + global newLclick + global xloc + global yloc + global newRclick + if event == 1: + newLclick = 1 + xloc = x + yloc = y + if event == 2: + newRclick = 1 + xloc = x + yloc = y + + +def thermal(): + + serdev = '/dev/ttyACM0' #change this if needed to your mbed serial dev. + mbed = serial.Serial(serdev, 921600) + + + size = 60, 80 + m = numpy.zeros(size, dtype=numpy.float32) + count = 0; + start = time.time() + isSyncronised = 's' + while (True): + count = count+1 + if count%30 == 0: + print(30/(time.time() - start),'fps') + start = time.time() + + while (ord(isSyncronised) != 0xde): + isSyncronised = mbed.read(1) + + while (ord(isSyncronised) != 0xad): + isSyncronised = mbed.read(1) + + while (ord(isSyncronised) != 0xbe): + isSyncronised = mbed.read(1) + + while (ord(isSyncronised) != 0xef): + isSyncronised = mbed.read(1) + + packingStruct = struct.Struct('BBBB') + unpackingStruct = struct.Struct('>i') + + for x in range(60): + for y in range(80): + a = mbed.read(1) + b = mbed.read(1) + m[x][y] = (ord(a)*255 + ord(b)) + global newLclick + global xloc + global yloc + global newRclick + global min + global max + mult = 8 #just a scaling to make things easier to see. set to 1 for native + if( newLclick == 1): + print( yloc), + print( xloc) + min = m[ yloc/mult][ xloc/mult] + newLclick = 0 + if( newRclick == 1): + max = m[ yloc/mult][ xloc/mult] + newRclick = 0 + + m = (m - min)/(max-min + 0.0) + bigm = cv2.resize(m, (80*mult,60*mult)) + bigm = bigm * 255 + cvuint8 = cv2.convertScaleAbs(bigm) + + im_color = cv2.applyColorMap(cvuint8, cv2.COLORMAP_RAINBOW) + cv2.imshow('Thermal Image', im_color) + cv2.setMouseCallback('Thermal Image', onMouse, param=None) + cv2.waitKey(1) + + +if __name__ == '__main__': + thermal() diff --git a/software/MbedLPC1768/MbedLPC1768Lepton.cpp b/software/MbedLPC1768/MbedLPC1768Lepton.cpp new file mode 100644 index 0000000..21efab2 --- /dev/null +++ b/software/MbedLPC1768/MbedLPC1768Lepton.cpp @@ -0,0 +1,155 @@ +/* +Copyright (c) 2015, Josh Elsdon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "mbed.h" +#include "MODSERIAL.h" +MODSERIAL pc(USBTX, USBRX, 1024,256); +SPI lepton_spi(p5, p6, p7); +DigitalOut spi_cs(p8); + +#define VOSPI_FRAME_SIZE (164) + +uint8_t image0[60][160]; +uint8_t image1[60][160]; + +DigitalOut led(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); +int frameAvailable = 0; +int bufferToReadFrom = 1; +int imageReading = 0; +int packet_number = 0; + +Ticker checkCam; // interval timer to check the cam. + +//ok: the plan there will be 2 buffers that are ping ponged +// one recieving the new data while the other one is outputted +// they then can swap at the end of the output. +// The high priority process is reading the lepton. +// The readout will be done as a background process. +// The lepton will be read continuously till there are scrap packets. +// a timer will make the check for new packets at 50%of the fps.(27). +//This will run at 5fps on LPC1768 mbed, TODO: use DMA to get it to 9Hz +//This will work well on any mbed with changes to the pin assignments above. + + +void LeptonCheck() +{ + led = 1; + led2 = 0; + bool junk = 0; + while(!junk) { + uint8_t header[4]; + spi_cs = 0; + //check the header for junk marker, also take packet count. + for(int i=0; i<4; i++) { + header[i] = lepton_spi.write(0x00); + } + + //decide junk + if (header[0] &0xf == 0x0f) { + junk = true; + } else { + junk = false; + } + + if(!junk) { + imageReading =1; + packet_number = header[1]; + } + + + if(bufferToReadFrom == 1) { //choose buffer to right in. + for(int i=0; i