MP3-capable chair with sensor-embedded weight scale.
Dependencies: HysteresisIn LCD SDFileSystem VS1053 mbed
Revision 0:0451ba2f1062, committed 2013-12-20
- Comitter:
- kayekss
- Date:
- Fri Dec 20 21:35:07 2013 +0000
- Commit message:
- First commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HysteresisIn.lib Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/kayekss/code/HysteresisIn/#fe43537bd3d6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD.lib Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/yamaguch/code/LCD/#b3def1d4f466
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VS1053.lib Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/kayekss/code/VS1053/#1f57fbd3aeb5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defs.h Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,36 @@ +#ifndef ISU_PROJECT_DEFS_H_ +#define ISU_PROJECT_DEFS_H_ + +// Input thresholds +#define HIGH_TO_LOW 0.25 +#define LOW_TO_HIGH 0.75 + +// Delay count until settling +#define SETTLING_COUNT 5 + +// Polling interval (second) +#define POLL_INTERVAL_SEC 0.50 + +// Block size of read/write (byte) +#define BLOCK_SIZE 1024 + +typedef enum { + CANCELING = -1, + STOPPING = -2, + READY = 0, + PLAYING1 = 1, + PLAYING2 = 2, + PLAYING3 = 3, + PLAYING4 = 4 +} State; + +typedef enum { + STOP_REQUEST = -1, + NONE = 0, + PLAY1_REQUEST = 1, + PLAY2_REQUEST = 2, + PLAY3_REQUEST = 3, + PLAY4_REQUEST = 4 +} Request; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,269 @@ +#include <stdio.h> +#include "mbed.h" +#include "defs.h" +#include "pinalias.h" +#include "HysteresisIn.h" +#include "SDFileSystem.h" +#include "VS1053.h" +#include "LCD.h" + +SDFileSystem sd(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13, /*CS*/ D10, "sd"); +VS1053 mp3(/*MOSI*/ D11, /*MISO*/ D12, /*SCK*/ D13, + /*CS*/ D9, /*BSYNC*/ D8, /*DREQ*/ D7, /*RST*/ D6, /*SPI freq.*/ 6000000); +HysteresisIn sens3(A3, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) +HysteresisIn sens2(A2, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 +HysteresisIn sens1(A1, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 +HysteresisIn sens0(A0, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) +LCD lcd(/*SDA*/ D107, /*SCL*/ D106, /*RESET*/ D105, /*Backlight*/ NC, + /*Contrast*/ 40); +BusOut led(/*Red*/ P3, /*Yellow*/ P4, /*Green*/ P5, /*Blue*/ P6, /*White*/ P7); +Ticker tic; + +const char *fileNameList[] = { + "", + "/sd/Track1.mp3", + "/sd/Track2.mp3", + "/sd/Track3.mp3", + "/sd/Track4.mp3" +}; + +volatile State state = READY; +volatile Request request = NONE; + +/** Setups and initializations */ +void setup(void) { + // Initialize VS1053 + mp3.hardwareReset(); + mp3.clockUp(); + wait(0.1); + + // Setup LCD + lcd.reset(); + lcd.cls(); + + // Initialize LCD + led = 0x00; +} + +/** Read voltages from photo sensor pins and detect weightscale point code */ +int readPhotoSensors(void) { + uint8_t bitPattern; + + // Read all photo sensor inputs + bitPattern = sens3.read() << 3 + | sens2.read() << 2 + | sens1.read() << 1 + | sens0.read(); + + switch (bitPattern) { + // 1 when open, 0 when shut + // Higher bit is on outer side + case 0xf: // 1111: no load + return 0; + case 0xe: // 1110: slight load + return 1; + case 0xc: // 1100 + return 2; + case 0x8: // 1000 + return 3; + case 0x0: // 0000: heavy load + return 4; + default: // Other than expectation: erroneous pattern + return -1; + } +} + +/** Poll/sample weightscale inputs and issue requests */ +void pollAndRequest() { + const char* stateNameList[] = { + "STOPPING", // -2 + "CANCELING", // -1 + "READY", // 0 + "PLAYING1", // 1 + "PLAYING2", // 2 + "PLAYING3", // 3 + "PLAYING4" // 4 + }; + const uint8_t ledPatternList[] = { + 0x10, // -1 STOP_REQUEST W---- + 0x00, // 0 NONE ----- + 0x01, // 1 PLAY1_REQUEST ----R + 0x02, // 2 PLAY2_REQUEST ---Y- + 0x04, // 3 PLAY3_REQUEST --G-- + 0x08 // 4 PLAY4_REQUEST -B--- + }; + int code; + static int codePrev = 0; + static uint8_t holdTimes = 0; + + // Get weightscale point code by reading photo sensors + code = readPhotoSensors(); + + // Count the times that the given code persists + if (code == codePrev && code != -1) { + if (holdTimes < 99) { + holdTimes++; + } + } else { + holdTimes = 0; + } + lcd.locate(0, 0); + lcd.printf("%-15s", stateNameList[state + 2]); + lcd.locate(0, 1); + lcd.printf("ps=%2d times=%2d", code, holdTimes); + + // Once the point is stable enough, make a request + if (holdTimes == SETTLING_COUNT) { + if (code == 0) { + // Stable no load: stop request + request = STOP_REQUEST; + } else { + // Certain stable load: play request 1..4 + // Ignore cases while playing the same track + if (state != code) { + request = (Request) code; + } + } + } + + // Set LED as the request + led = ledPatternList[request + 1]; + + // Preserve this time's code + codePrev = code; +} + +/** Player control in accordance with requests */ +void controlTrack() { + static FILE *fp = NULL; + size_t sizeRead = 0; + uint8_t buf[BLOCK_SIZE]; + static size_t totalSizeSent = 0; + + switch (state) { + case READY: + switch (request) { + case STOP_REQUEST: + // Clear stop request + request = NONE; + break; + case PLAY1_REQUEST: case PLAY2_REQUEST: case PLAY3_REQUEST: case PLAY4_REQUEST: + fp = fopen(fileNameList[request], "rb"); + if (fp) { + totalSizeSent = 0; + state = (State) request; + lcd.locate(15, 0); + lcd.printf("*"); + } + // Clear play request + request = NONE; + break; + default: + break; + } + break; + case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: + if (request == NONE) { + if (feof(fp)) { + // Close the track + fclose(fp); + lcd.locate(15, 0); + lcd.printf(" "); + + // Invoke play request again + request = (Request) state; + state = READY; + } else { + sizeRead = fread(buf, sizeof(char), BLOCK_SIZE, fp); + totalSizeSent += mp3.sendDataBlock(buf, sizeRead); + } + } else { + // Cancel current track when something's requested + fclose(fp); + lcd.locate(15, 0); + lcd.printf(" "); + state = CANCELING; + } + break; + case CANCELING: + if (mp3.sendCancel()) { + state = STOPPING; + } + break; + case STOPPING: + if (mp3.stop()) { + state = READY; + } + if (request == STOP_REQUEST) { + // Clear stop request + request = NONE; + } + break; + default: + break; + } +} + +/** Main routine */ +int main(void) { + FILE *fpTest = NULL; + time_t secBuild; + struct tm *tmBuild; + char sbuf[10]; + bool sdTestResult = 0x00; + + setup(); + + // Print build timestamp (in JST) + secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60; + tmBuild = localtime(&secBuild); + + strftime(sbuf, 10, "%Y-%m-%d", tmBuild); + lcd.locate(0, 0); + lcd.printf("Build %8s", sbuf); + wait(0.0); + strftime(sbuf, 10, "%H:%M:%S", tmBuild); + lcd.locate(0, 1); + lcd.printf(" T%8s", sbuf); + wait(2.0); + + // SD card test + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("No memory cards "); + wait(0.0); + lcd.locate(0, 0); + lcd.printf("Track / / / Ok"); + for (uint8_t i = 1; i <= 4; i++) { + fpTest = fopen(fileNameList[i], "rb"); + if (fpTest) { + lcd.locate(2 * i + 4, 0); + lcd.printf("%d", i); + fclose(fpTest); + } else { + sdTestResult |= 0x01 << (i - 1); + } + } + lcd.locate(0, 1); + if (sdTestResult == 0x00) { + lcd.printf("SD Test Pass "); + } else { + lcd.printf("SD Test Fail "); + while (1) { + led = sdTestResult; + wait(0.5); + led = 0x00; + wait(0.5); + } + } + wait(1.0); + lcd.cls(); + + // Set Ticker interrupt routine + tic.attach(&pollAndRequest, POLL_INTERVAL_SEC); + + // Main loop + while (1) { + controlTrack(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/f37f3b9c9f0b \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pinalias.h Fri Dec 20 21:35:07 2013 +0000 @@ -0,0 +1,40 @@ +#ifndef PIN_ALIAS_H_ +#define PIN_ALIAS_H_ + +// Pin aliases for KL25Z +#define D100 PTC7 +#define D101 PTC0 +#define D102 PTC3 +#define D103 PTC4 +#define D104 PTC5 +#define D105 PTC6 +#define D106 PTC10 +#define D107 PTC11 +#define D108 PTC12 +#define D109 PTC13 +#define D110 PTC16 +#define D111 PTC17 +#define D112 PTA16 +#define D113 PTA17 +#define D114 PTE31 +#define D115 NC +#define D116 PTD6 +#define D117 PTD7 + +#define A10 PTC20 +#define A11 PTC21 +#define A12 PTC22 +#define A13 PTC23 +#define A14 PTC29 +#define A15 PTC30 + +#define P0 PTB8 +#define P1 PTB9 +#define P2 PTB10 +#define P3 PTB11 +#define P4 PTE2 +#define P5 PTE3 +#define P6 PTE4 +#define P7 PTE5 + +#endif