Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LPC1768 variant. #20

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
128 changes: 128 additions & 0 deletions software/MbedLPC1768/LeptonRead.py
Original file line number Diff line number Diff line change
@@ -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()
155 changes: 155 additions & 0 deletions software/MbedLPC1768/MbedLPC1768Lepton.cpp
Original file line number Diff line number Diff line change
@@ -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<VOSPI_FRAME_SIZE-4; i++) {
if(!junk) {
image0[packet_number][i] = lepton_spi.write(0x00);
} else {
uint8_t waste = lepton_spi.write(0x00);// waste these they are junk
}
}
} else {
for(int i=0; i<VOSPI_FRAME_SIZE-4; i++) {
if(!junk) {
image1[packet_number][i] = lepton_spi.write(0x00);
} else {
uint8_t waste = lepton_spi.write(0x00);
}
}
}
spi_cs = 1;
if(packet_number == 59 && !junk) {
imageReading = 0;
frameAvailable = 1;
}
}
led = 0;
led2 = 1;

}

void sendPic(int bufferNo)
{

// tag the beginning of an image with 'deadbeef'
pc.putc(0xDE);
pc.putc(0xAD);
pc.putc(0xBE);
pc.putc(0xEF);
if(bufferNo == 0) {//use the buffer that is not being written to.
for(int i = 0; i < 60; i++) {
for(int j = 0; j < 160; j++) {
pc.putc(image0[i][j]);
}
}
} else {
for(int i = 0; i < 60; i++) {
for(int j = 0; j < 160; j++) {
pc.putc(image1[i][j]);
}
}
}
}


int main()
{


pc.baud(921600);
lepton_spi.format(8,3);
lepton_spi.frequency(17000000); //upto 20M when not on a breadboard.
spi_cs = 1;
spi_cs = 0;
spi_cs = 1;
wait_ms(185);
checkCam.attach(&LeptonCheck, (1.0/(27*1.6))); //check every half frame.

while(1) {
if(frameAvailable) {
sendPic(bufferToReadFrom);
while(imageReading) {} // block here till current grab is complete
bufferToReadFrom = 1-bufferToReadFrom;
}
}
}