MP3-capable chair with sensor-embedded weight scale.
Dependencies: ACM1602 SDFileSystem VS1053 mbed ClockControl PowerControl
Revision 0:d9789f57fd9d, committed 2014-03-26
- Comitter:
- kayekss
- Date:
- Wed Mar 26 19:56:18 2014 +0000
- Child:
- 1:ef257d63d970
- Commit message:
- MP3-capable chair with sensor-embedded weight scale.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ACM1602.lib Wed Mar 26 19:56:18 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/kayekss/code/ACM1602/#f81621685b23
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HysteresisIn.lib Wed Mar 26 19:56:18 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/kayekss/code/HysteresisIn/#fe43537bd3d6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Wed Mar 26 19:56:18 2014 +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 Wed Mar 26 19:56:18 2014 +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 Wed Mar 26 19:56:18 2014 +0000 @@ -0,0 +1,77 @@ +#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; + +PinName const xp5 = P0_9; // SPI1 + MOSI +PinName const xp6 = P0_8; // | MISO +PinName const xp7 = P0_7; // | SCK +PinName const xp8 = P0_6; // | SSEL# +PinName const xp9 = P0_0; // UART3+ Tx I2C1 + SDA +PinName const xp10 = P0_1; // | Rx | SCL +PinName const xp11 = P0_18; // SPI0 + MOSI +PinName const xp12 = P0_17; // | MISO +PinName const xp13 = P0_15; // UART1+ Tx | SCK +PinName const xp14 = P0_16; // | Rx | SSEL# +PinName const xp15 = P0_23; // AnalogIn +PinName const xp16 = P0_24; // AnalogIn +PinName const xp17 = P0_25; // AnalogIn +PinName const xp18 = P0_26; // AnalogIn AnalogOut +PinName const xp19 = P1_30; // AnalogIn +PinName const xp20 = P1_31; // AnalogIn +PinName const xp21 = P0_2; +PinName const xp22 = P0_3; +PinName const xp23 = P0_21; +PinName const xp24 = P0_22; +PinName const xp25 = P0_27; // **Open drain +PinName const xp26 = P0_28; // **Open drain +PinName const xp27 = P2_13; +PinName const xp53 = P2_12; +PinName const xp52 = P2_11; +PinName const xp51 = P2_10; +PinName const xp50 = P2_8; +PinName const xp49 = P2_7; +PinName const xp48 = P2_6; +PinName const xp47 = P2_5; // PwmOut +PinName const xp46 = P2_4; // PwmOut +PinName const xp45 = P2_3; // PwmOut +PinName const xp44 = P2_2; // PwmOut +PinName const xp43 = P2_1; // PwmOut +PinName const xp42 = P2_0; // PwmOut +PinName const xp41 = P0_11; // UART2+ Rx I2C2 + SCL +PinName const xp40 = P0_10; // | Tx | SDA +PinName const xp39 = P0_5; // CAN + TD +PinName const xp38 = P0_4; // | RD +PinName const LED0 = P0_22; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Mar 26 19:56:18 2014 +0000 @@ -0,0 +1,294 @@ +#include <stdio.h> +#include "mbed.h" +#include "defs.h" +#include "HysteresisIn.h" +#include "SDFileSystem.h" +#include "VS1053.h" +#include "ACM1602.h" + +// Pin settings for LPC1768(LPCXpresso) +SDFileSystem sd(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13, /*CS*/ xp53, /*Mountpoint*/ "sd"); +VS1053 mp3(/*MOSI*/ xp11, /*MISO*/ xp12, /*SCK*/ xp13, + /*CS*/ xp52, /*BSYNC*/ xp51, /*DREQ*/ xp50, /*RST*/ xp49, /*SPI freq.*/ 6000000); +HysteresisIn sens3(p17, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) +HysteresisIn sens2(p18, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 +HysteresisIn sens1(p19, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 +HysteresisIn sens0(p20, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) +ACM1602 lcd(/*SDA*/ xp9, /*SCL*/ xp10, /*Address*/ 0xa0); +DigitalOut led(LED0); +DigitalOut audioPower(xp38); +Ticker tic; + +// Pin settings for LPC1114FN28 (SD card accessing does not work) +// SDFileSystem sd(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6, /*CS*/ dp4, /*Mountpoint*/ "sd"); +// VS1053 mp3(/*MOSI*/ dp2, /*MISO*/ dp1, /*SCK*/ dp6, +// /*CS*/ dp14, /*BSYNC*/ dp17, /*DREQ*/ dp18, /*RST*/ dp25, /*SPI freq.*/ 4000000); +// HysteresisIn sens3(dp9, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #3 (Outer) +// HysteresisIn sens2(dp10, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #2 +// HysteresisIn sens1(dp11, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #1 +// HysteresisIn sens0(dp13, HIGH_TO_LOW, LOW_TO_HIGH, 1); // Photo sensor #0 (Inner) +// ACM1602 lcd(/*SDA*/ dp5, /*SCL*/ dp27, /*Address*/ 0xa0); +// 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; + +/** Setup and initializations */ +void setup(void) { + // Initialize VS1053 + mp3.hardwareReset(); + mp3.clockUp(); + wait(0.1); + + // Initialize power supply for audio amplifier circuit + audioPower = 0; + + // Setup LCD + lcd.init(); + + // Initialize LED + led = 0; +} + +/** 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 + }; + 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; + } + } + } + + // 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 - 1], "rb"); + if (fp) { + // Power supply on + audioPower = 1; + led = 1; + + totalSizeSent = 0; + state = (State) request; + lcd.locate(15, 0); + lcd.printf("*"); + } else { + lcd.locate(0, 1); + lcd.printf("File Open Error "); + } + // Clear play request + request = NONE; + break; + default: + break; + } + break; + case PLAYING1: case PLAYING2: case PLAYING3: case PLAYING4: + if (request == NONE) { + sizeRead = fread(buf, sizeof(uint8_t), BLOCK_SIZE, fp); + if (sizeRead) { + totalSizeSent += mp3.sendDataBlock(buf, sizeRead); + } else { + // Close the track + fclose(fp); + lcd.locate(15, 0); + lcd.printf(" "); + + // Invoke play request again + request = (Request) state; + state = READY; + } + } 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; + + // Power supply off + audioPower = 0; + led = 0; + } + break; + default: + break; + } +} + +/** Print build timestamp (in JST) */ +void printTimestamp() { + time_t secBuild; + struct tm *tmBuild; + char sbuf[11]; + + secBuild = MBED_BUILD_TIMESTAMP + 9 * 60 * 60; + tmBuild = localtime(&secBuild); + + strftime(sbuf, 11, "%Y-%m-%d", tmBuild); + lcd.locate(0, 0); + lcd.printf("Build %8s", sbuf); + wait(0.0); + strftime(sbuf, 11, "%H:%M:%S", tmBuild); + lcd.locate(0, 1); + lcd.printf(" T%8s", sbuf); + wait(2.0); +} + +/** Test files in the SD memory card */ +uint8_t testFiles() { + FILE *fpTest = NULL; + bool sdTestResult = 0x00; + + 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 - 1], "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 "); + wait(1.0); + lcd.cls(); + } else { + lcd.printf("SD Test Fail "); + } + return sdTestResult; +} + +/** Main routine */ +int main(void) { + setup(); + + // Print build timestamp + printTimestamp(); + + // Test files: Enter an infinite loop on failure + if (testFiles()) { + while (1) { + led = 1; + wait(0.5); + led = 0; + wait(0.5); + } + } + + // 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 Wed Mar 26 19:56:18 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/7d30d6019079 \ No newline at end of file