
HIT Project #3 https://community.freescale.com/docs/DOC-99621
Dependencies: EthernetInterface WebSocketClient mbed-rtos mbed
MonkeyDo!
These are the demo files for Freescale HIT project #3: Monkey Do. It uses a FRDM-AUTO + a FRDM-K64F to demo websockets for a simple IoT application.
See the main MonkeyDo page for all of the schematics, videos, GitHub links, etc for everything else!
https://community.freescale.com/docs/DOC-99621
Revision 0:29f58b9daa2c, committed 2014-07-04
- Comitter:
- emh203
- Date:
- Fri Jul 04 22:55:47 2014 +0000
- Child:
- 1:d87a428e88ee
- Commit message:
- 1st add
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetInterface.lib Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/EthernetInterface/#e6b79f0ccd95
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/IO.cpp Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,13 @@ +#include "System.h" + +DigitalOut SSR_HIGH_CURRENT_1(PTC3); +DigitalOut SSR_HIGH_CURRENT_2(PTC2); + +DigitalOut SSR_LOW_CURRENT_1(PTC1); +DigitalOut SSR_LOW_CURRENT_2(PTC8); + +AnalogIn TempSensor(PTB11); + +Serial PC(PTB17, PTB16); + +extern EthernetInterface eth;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/IO.h Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,28 @@ +#include "System.h" +#include "EthernetInterface.h" + +#ifndef _IO_H +#define _IO_H + + +extern DigitalOut SSR_HIGH_CURRENT_1; +extern DigitalOut SSR_HIGH_CURRENT_2; + +extern DigitalOut SSR_LOW_CURRENT_1; +extern DigitalOut SSR_LOW_CURRENT_2; + +extern AnalogIn TempSensor; + +#define ENABLE_HIGH_CURRENT_RELAY SSR_HIGH_CURRENT_1 = 1; SSR_HIGH_CURRENT_2 = 1; +#define DISABLE_HIGH_CURRENT_RELAY SSR_HIGH_CURRENT_1 = 0; SSR_HIGH_CURRENT_2 = 0; + +#define ENABLE_LOW_CURRENT_RELAY SSR_LOW_CURRENT_1 = 1; SSR_LOW_CURRENT_2 = 1; +#define DISABLE_LOW_CURRENT_RELAY SSR_LOW_CURRENT_1 = 0; SSR_LOW_CURRENT_2 = 0; + + +extern Serial PC; + +extern EthernetInterface eth; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/Queue.cpp Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,98 @@ +#include "stdint.h" +#include "Queue.h" +#include <string.h> + +static char StringBuffer[256]; + +void InitByteQueue(ByteQueue *BQ,uint16_t Size,uint8_t * Storage) { + uint16_t i; + + BQ->QueueSize = Size; + BQ->ReadPtr=0; + BQ->WritePtr=0; + BQ->QueueStorage = Storage; + + for (i=0;i<BQ->QueueSize;i++) { + BQ->QueueStorage[i] = 0; + } +} + +uint16_t BytesInQueue(ByteQueue *BQ) { + if (BQ->ReadPtr > BQ->WritePtr) { + return (BQ->QueueSize - BQ->ReadPtr + BQ->WritePtr); + } else if (BQ->WritePtr > BQ->ReadPtr) { + return (BQ->WritePtr - BQ->ReadPtr); + } else { + return 0; + } +} + +int16_t ByteEnqueue(ByteQueue *BQ,uint8_t Val) { + if (BytesInQueue(BQ) == BQ->QueueSize - 1) { + return QUEUE_FULL; + } else { + BQ->QueueStorage[BQ->WritePtr] = Val; + BQ->WritePtr++; + + if (BQ->WritePtr >= BQ->QueueSize) { + BQ->WritePtr = 0; + } + return QUEUE_OK; + } +} + +int16_t ByteArrayEnqueue(ByteQueue *BQ,uint8_t *Buf,uint16_t Len) { + uint16_t i; + for (i=0;i<Len;i++) { + ByteEnqueue(BQ,Buf[i]); + } + return QUEUE_OK; +} + + +int16_t Qprintf(ByteQueue *BQ, const char *FormatString,...) +{ + + va_list argptr; + va_start(argptr,FormatString); + vsprintf((char *)StringBuffer,FormatString,argptr); + va_end(argptr); + + return ByteArrayEnqueue(BQ,(uint8_t *)StringBuffer,strlen(StringBuffer)); +} + + +int16_t ByteDequeue(ByteQueue *BQ,uint8_t *Val) { + + if (BytesInQueue(BQ) == 0) { + return QUEUE_EMPTY; + } else { + *Val = BQ->QueueStorage[BQ->ReadPtr]; + + BQ->ReadPtr++; + + if (BQ->ReadPtr >= BQ->QueueSize) { + BQ->ReadPtr = 0; + } + return QUEUE_OK; + } +} + +uint8_t ForcedByteDequeue(ByteQueue *BQ) +{ + uint8_t RetVal; + + if (BytesInQueue(BQ) == 0) { + return 0; + } else { + RetVal = BQ->QueueStorage[BQ->ReadPtr]; + + BQ->ReadPtr++; + + if (BQ->ReadPtr >= BQ->QueueSize) { + BQ->ReadPtr = 0; + } + return RetVal; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/Queue.h Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,34 @@ +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> + +#ifndef QUEUE_H_ +#define QUEUE_H_ + + +typedef struct { + + uint16_t ReadPtr; + uint16_t WritePtr; + uint16_t QueueSize; + uint8_t *QueueStorage; + +} ByteQueue; + +#define QUEUE_FULL -1 +#define QUEUE_EMPTY -2 +#define QUEUE_OK 0 + + +void InitByteQueue(ByteQueue *BQ,uint16_t Size,uint8_t * Storage); +uint16_t BytesInQueue(ByteQueue *BQ); +int16_t ByteEnqueue(ByteQueue *BQ,uint8_t Val); +int16_t ByteArrayEnqueue(ByteQueue *BQ,uint8_t *Buf,uint16_t); +int16_t ByteDequeue(ByteQueue *BQ,uint8_t *Val); +uint8_t ForcedByteDequeue(ByteQueue *BQ); +int16_t Qprintf(ByteQueue *BQ, const char *FormatString,...); + + + + +#endif /* TFC_QUEUE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/Terminal.cpp Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,261 @@ + +#include "Terminal.h" +#include "Types.h" +#include "Queue.h" +#include <string.h> +#include <stdint.h> + + +//***************************************************************** +//Terminal Configuration +//***************************************************************** + +#define MAX_TERMINAL_LINE_CHARS 64 +#define MAX_TERMINAL_CMD_CHARS 32 + +ByteQueue TERMINAL_OUTPUT_QUEUE; +ByteQueue TERMINAL_INPUT_QUEUE; + +#define TERMINAL_QUEUE_SIZE 512 + +uint8_t TERMINAL_OUTPUT_QUEUE_Storage[TERMINAL_QUEUE_SIZE]; +uint8_t TERMINAL_INPUT_QUEUE_Storage[TERMINAL_QUEUE_SIZE]; + + + +//Terminal Prototypes Here! +void TerminalCmd_Help(char *arg); +void TerminalCmd_ssr(char *arg); + +//Populate this array with the callback functions and their terminal command string +TerminalCallbackRecord MyTerminalCallbackRecords[] ={ {"help",TerminalCmd_Help,"Lists available commands"}, + {"ssr",TerminalCmd_ssr,"Enables /disables an ssr"} + + }; + + +#define NUM_TERMINAL_COMMANDS (sizeof(MyTerminalCallbackRecords)/sizeof(TerminalCallbackRecord)) + + +//Terminal Callback Implementation Here! + +void TerminalCmd_Help(char *arg) +{ + uint8_t i; + + TERMINAL_PRINTF("\r\n\r\nCommand List:\r\n"); + TERMINAL_PRINTF("----------------------\r\n"); + + for(i=0;i<NUM_TERMINAL_COMMANDS;i++) + { + TERMINAL_PRINTF("%s ----> %s\r\n",MyTerminalCallbackRecords[i].CommandString,MyTerminalCallbackRecords[i].HelpString); + } + + TERMINAL_PRINTF("\r\n\r\n"); +} + +void TerminalCmd_ssr(char *arg) +{ + uint32_t Items; + uint32_t RelayIndex; + uint32_t RelayState; + Items = sscanf(arg,"%d %d",&RelayIndex,&RelayState); + + if(Items!=2) + { + TERMINAL_PRINTF("\r\nssr requires 2 arguments:\r\n"); + TERMINAL_PRINTF("1st: Relay Index Valid values are 0 (high current) and 1 (low current)\r\n"); + TERMINAL_PRINTF("2nd: Relay State 0 == off 1 == on anything else == off\r\n"); + } + else + { + if(RelayIndex >1) + RelayIndex = 1; + + if(RelayState > 1) + RelayState = 0; + + TERMINAL_PRINTF("Setting ssr %d to state of %d",RelayIndex,RelayState); + + if(RelayIndex == 0) + { + if(RelayState == 0 ) + { + DISABLE_HIGH_CURRENT_RELAY ; + } + else + { + ENABLE_HIGH_CURRENT_RELAY; + } + } + else + { + if(RelayState == 0 ) + { + DISABLE_LOW_CURRENT_RELAY; + } + else + { + ENABLE_LOW_CURRENT_RELAY; + } + } + + + } +} + + + + +//***************************************************************** +//Plumbing..... +//***************************************************************** + + + +char TerminalLineBuf[MAX_TERMINAL_LINE_CHARS]; +uint8_t TerminalPos; +char TerminalCmdBuf[MAX_TERMINAL_CMD_CHARS+1]; +char TerminalArgs[MAX_TERMINAL_LINE_CHARS-MAX_TERMINAL_CMD_CHARS]; +uint8_t NextCharIn; +uint8_t CmdFound; + +void TerminalBootMsg() +{ + // TERMINAL_PRINTF("\r\n\r\nMonkey Do!\r\n"); +} + +void InitTerminal() +{ + TerminalPos = 0; + CmdFound = 0; + + InitByteQueue(&TERMINAL_OUTPUT_QUEUE,TERMINAL_QUEUE_SIZE,&TERMINAL_OUTPUT_QUEUE_Storage[0]); + InitByteQueue(&TERMINAL_INPUT_QUEUE,TERMINAL_QUEUE_SIZE,&TERMINAL_INPUT_QUEUE_Storage[0]); + + + // TerminalBootMsg(); +} + + + +void ProcessTerminal() +{ + uint8_t i,j; + uint8_t ArgsFound; + + if(TERMINAL_READABLE) + { + NextCharIn = TERMINAL_GETC; + + switch(NextCharIn) + { + case '\r': + + TerminalLineBuf[TerminalPos++] = 0x0; + TERMINAL_PUTC(NextCharIn); + + if(TerminalPos > 1) + { + //find the command + i=0; + while(TerminalLineBuf[i]>0x20 && TerminalLineBuf[i]<0x7f) + { + TerminalCmdBuf[i] = TerminalLineBuf[i]; + i++; + + if(i==MAX_TERMINAL_CMD_CHARS) + { + break; + } + } + + TerminalCmdBuf[i] = 0; + TerminalCmdBuf[i+1] = 0; + + + ArgsFound = TRUE; + memset(TerminalArgs,0x00,sizeof(TerminalArgs)); + //scan for num terminator or next non whitespace + while(TerminalLineBuf[i]<=0x20 && (i<MAX_TERMINAL_LINE_CHARS)) + { + if(TerminalLineBuf[i] == 0x00) + { + + //if we find a NULL terminator before a non whitespace character they flag for no arguments + ArgsFound = FALSE; + break; + } + i++; + } + + if(ArgsFound == TRUE) + { + strcpy(TerminalArgs,&TerminalLineBuf[i]); + + //trim trailing whitespace + i = sizeof(TerminalArgs)-1; + + while((TerminalArgs[i]<0x21) && (i>0)) + { + TerminalArgs[i]= 0x00; + i--; + } + } + + CmdFound = FALSE; + for(j=0;j<NUM_TERMINAL_COMMANDS;j++) + { + if(strcmp(TerminalCmdBuf,MyTerminalCallbackRecords[j].CommandString) == 0) + { + TERMINAL_PRINTF("\r\n"); + if(MyTerminalCallbackRecords[j].Callback != NULL) + MyTerminalCallbackRecords[j].Callback(TerminalArgs); + + CmdFound = TRUE; + break; + } + } + if(CmdFound == FALSE) + { + TERMINAL_PRINTF("\r\n%s command not recognized.\r\n\r\n",TerminalCmdBuf); + + } + } + TERMINAL_PRINTF("\r\n>"); + TerminalPos = 0; + + break; + + case '\b': + if(TerminalPos > 0) + { + TerminalPos--; + TERMINAL_PUTC(NextCharIn); + } + break; + + default: + + if(TerminalPos == 0 && NextCharIn == 0x020) + { + //Do nothing if space bar is pressed at beginning of line + } + else if(NextCharIn >= 0x20 && NextCharIn<0x7F) + { + + if(TerminalPos < MAX_TERMINAL_LINE_CHARS-1) + { + TerminalLineBuf[TerminalPos++] = NextCharIn; + TERMINAL_PUTC(NextCharIn); + } + } + + break; + + } + } + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/Terminal.h Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,35 @@ + +#include "System.h" +#include "Queue.h" + +#ifndef TFC_TERMINAL_H_ +#define TFC_TERMINAL_H_ + + +extern ByteQueue TERMINAL_OUTPUT_QUEUE; +extern ByteQueue TERMINAL_INPUT_QUEUE; + + +void InitTerminal(); +void ProcessTerminal(); + + #define TERMINAL_PRINTF(...) Qprintf(&TERMINAL_OUTPUT_QUEUE,__VA_ARGS__) + #define TERMINAL_PUTC(c) ByteEnqueue(&TERMINAL_OUTPUT_QUEUE,c) + #define TERMINAL_READABLE BytesInQueue(&TERMINAL_INPUT_QUEUE) + #define TERMINAL_GETC ForcedByteDequeue(&TERMINAL_INPUT_QUEUE) + + +typedef void (*TerminalCallback)(char *); + +typedef struct +{ + const char *CommandString; + TerminalCallback Callback; + const char *HelpString; + +} TerminalCallbackRecord; + + + + +#endif /* TFC_TERMINAL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GLUE/Types.h Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,13 @@ + +#ifndef TFC_TYPES_H_ +#define TFC_TYPES_H_ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* TFC_TYPES_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/System.h Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,14 @@ + +#ifndef _SYSTEM_H +#define _SYSTEM_H + +#include "mbed.h" +#include "stdint.h" +#include "Queue.h" +#include "Terminal.h" +#include "Types.h" +#include "IO.h" +#include "EthernetInterface.h" +#include "Websocket.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebSocketClient.lib Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/samux/code/WebSocketClient/#4567996414a5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,142 @@ +#include "System.h" + +char StringBuffer[256]; + + +#define TEMPERATURE_FILTER_SIZE 16 + +float TemperatureFilterBuffer[TEMPERATURE_FILTER_SIZE] = {0}; + +uint32_t TemperatureFilterIndex = 0; + +float Temperature = 0; + +Ticker SystemTicker; + +volatile uint32_t SensorUpdateTicker = 0; + +//This is used for some general purpose timing in the main loop +void SystemTick() +{ + if(SensorUpdateTicker < 0xFFFFFFFF) + SensorUpdateTicker++; +} + +int main() +{ + uint32_t i; + + DISABLE_HIGH_CURRENT_RELAY; + DISABLE_LOW_CURRENT_RELAY; + + InitTerminal(); //Initialize the Terminal State machine + + // enable the usb uart rx fifo + // UART_PFIFO_REG(UART0) |= 0x08; + + //Setup ouur ticker for 1mS + SystemTicker.attach_us(SystemTick,1000); + + PC.printf("\r\n\r\nMonkey Do!\r\n"); + + + PC.printf("Ethernet Init!\r\n"); + eth.init(); //Use DHCP + eth.connect(); + PC.printf("IP Address is %s\r\n", eth.getIPAddress()); + + Websocket ws("ws://sockets.mbed.org:443/ws/emh203/rw"); + + ws.connect(); + + while (1) { + + //Send sensor data to the websocket every second + if(SensorUpdateTicker >= 1000) + { + SensorUpdateTicker = 0; + + Temperature = 0; + + //Take a bunch of measurements and average to help with Data converter Noise + + for(i=0;i<TEMPERATURE_FILTER_SIZE;i++) + { + Temperature += ((TempSensor.read() * 3.3)// * //convert to volts + - 0.500) // subtract off 0c offset .... you may need to calibrate... see MCP9700A-E/TO data sheet + * 100; // Scale to Degrees C + } + Temperature = Temperature / TEMPERATURE_FILTER_SIZE; + + sprintf(StringBuffer,"temp %.1f\r\n",Temperature); + ws.send(StringBuffer); + } + + //See if we have an incoming command, if so process it + if(ws.read(StringBuffer) == true) + { + //our command structure is a simple ascii string. + // + //Cmd arg1 arg2 ..... + // + //The command is the 1st string. Each argument is separated by white space + // + //for example: + // + //ssr 1 0 + // + //is the "ssr" command with 2 arguments: 1 and 0 + // + // + //There are many ways to process a command but I will use my "Terminal" processor + //It normally is used to emulated a basic command line terminal from a serial port but it + //can easily process ourwebsocket data. + // + // + + + + //see if this is the command we sent out. The Mbed Websocket server sends input messagest + //to all who are attached. This means we get our own messages back. + + if(strncmp(StringBuffer,"temp",4) == 0) + { + //this means we go the temp message back, do nothing + } + else + { + //The first thing to do is copy the data into the terminal input queue + ByteArrayEnqueue(&TERMINAL_INPUT_QUEUE,(uint8_t *)StringBuffer,strlen(StringBuffer)); + //We also need a put in a new line character so the terminal will think a new command has been entered + ByteEnqueue(&TERMINAL_INPUT_QUEUE,'\r'); + } + + //Now that the data is in the terminal input queue, the ProcessTerminal() function will do the rest + } + + //This will process any incoming data to the terminal + ProcessTerminal(); + + //In addition to the websocket interface, we will also have a simple virtual command line terminal over the USB virtual com port. + //As of 2014-06-24 the Serial IRQ routines are not function in the mbed libraries for the FRDM-K64. For the mean time + //We will just manually shuffle data in and out of the terminal queues. The baud rate is slow enough in that the main loop will have plenty of time to + //move everything. Ideally I would want interrupts to keep everything flowing but this will be good enough for now. + + + if(PC.readable()) { + ByteEnqueue(&TERMINAL_INPUT_QUEUE,PC.getc()); + } + if(BytesInQueue(&TERMINAL_OUTPUT_QUEUE)>0) { + if(PC.writeable()) { + PC.putc(ForcedByteDequeue(&TERMINAL_OUTPUT_QUEUE)); + } + } + + } + + + +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-rtos.lib Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed-rtos/#ac8d036315ed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Jul 04 22:55:47 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721 \ No newline at end of file