|
#include "FS.h"
|
|
#include "ArduinoAdaptor.h"
|
|
#include <ESP32Time.h>
|
|
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
|
|
//#include "SD.h"
|
|
#include <TFT_eSPI.h> // Hardware-specific library
|
|
#include <SPI.h>
|
|
#include <NSP32.h>
|
|
#include <string.h>
|
|
|
|
ESP32Time rtc;
|
|
using namespace NanoLambdaNSP32;
|
|
//**********************************************
|
|
//壓感pin
|
|
int ADC_data=0;
|
|
#define ADC_PIN 35
|
|
//**********************************************
|
|
//SD CARD PIN 改 NSP32
|
|
#define VSPI_MISO 19
|
|
#define VSPI_MOSI 23
|
|
#define VSPI_SCLK 18
|
|
//#define VSPI_SS 5
|
|
|
|
const unsigned int PinRst = 21;
|
|
const unsigned int PinReady = 17;
|
|
|
|
ArduinoAdaptor adaptor(PinRst); // master MCU adaptor
|
|
NSP32 nsp32(&adaptor, NSP32::ChannelSpi); // NSP32 (using SPI channel)
|
|
|
|
int NOP = 0; // number of points
|
|
|
|
void PinReadyTriggerISR() {
|
|
// make sure to call this function when receiving a ready trigger from NSP32
|
|
nsp32.OnPinReadyTriggered();
|
|
}
|
|
/**********************************************
|
|
//for data file
|
|
File dataFile;
|
|
char* line[157];
|
|
String lines[150] ={};
|
|
int lineNum = 0;
|
|
int lines_to_read = 121;//想讀取的列數
|
|
**********************************************/
|
|
|
|
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
|
|
|
|
// This is the file name used to store the calibration data
|
|
// You can change this to create new calibration files.
|
|
// The SPIFFS file name must start with "/".
|
|
#define CALIBRATION_FILE "/TouchCalData1"
|
|
|
|
// Set REPEAT_CAL to true instead of false to run calibration
|
|
// again, otherwise it will only be done once.
|
|
// Repeat calibration if you change the screen rotation.
|
|
#define REPEAT_CAL false
|
|
|
|
#define KEY_X 40 //按鍵位置
|
|
#define KEY_Y 240 //按鍵位置
|
|
#define KEY_W 72 //按鍵寬度
|
|
#define KEY_H 32 //按鍵高度
|
|
#define KEY_SPACING_X 5 // 按鍵間距
|
|
#define KEY_SPACING_Y 20 // 按鍵間距
|
|
#define KEY_TEXTSIZE 1 // Font size multiplier
|
|
|
|
// Using two fonts since numbers are nice when bold
|
|
#define LABEL1_FONT &FreeSansOblique12pt7b // Key label font 1
|
|
#define LABEL2_FONT &FreeSansBold12pt7b // Key label font 2
|
|
|
|
#define DISP_X 20 //示波畫面左上角X位置
|
|
#define DISP_Y 10 //示波畫面左上角y位置
|
|
#define DISP_W 182 //示波畫面寬度
|
|
#define DISP_H 180 //示波畫面高度
|
|
#define DISP_TSIZE 10 //暫時不知道
|
|
#define DISP_TCOLOR TFT_RED //畫面圖的顏色
|
|
|
|
// Number length, buffer for storing it and character index
|
|
#define NUM_LEN 12
|
|
char numberBuffer[NUM_LEN + 1] = "";
|
|
uint8_t numberIndex = 0;
|
|
|
|
// We have a status line for messages
|
|
#define STATUS_X 120 // Centred on this
|
|
#define STATUS_Y 65
|
|
|
|
// Create 3 keys for the keypad
|
|
|
|
char keyLabel[3][7] = {"Start", "On", "Detect"};
|
|
uint16_t keyColor[3] = {TFT_DARKGREY, TFT_DARKGREY, TFT_DARKGREY};
|
|
|
|
// Invoke the TFT_eSPI button class and create all the button objects
|
|
TFT_eSPI_Button key[3];
|
|
|
|
//校正螢幕範圍
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
// Use serial port
|
|
pinMode(5,OUTPUT);
|
|
pinMode(15,OUTPUT);
|
|
pinMode(16,OUTPUT);
|
|
digitalWrite(5, HIGH);
|
|
digitalWrite(15, HIGH);
|
|
digitalWrite(16, HIGH);
|
|
|
|
Serial.begin(115200);
|
|
|
|
Serial.println("Ready");
|
|
|
|
//******************NSP32***********************
|
|
// initialize "ready trigger" pin for accepting external interrupt (falling edge trigger)
|
|
pinMode(PinReady, INPUT_PULLUP); // use pull-up
|
|
attachInterrupt(digitalPinToInterrupt(PinReady), PinReadyTriggerISR, FALLING); // enable interrupt for falling edge
|
|
|
|
// initialize NSP32
|
|
nsp32.Init();
|
|
// initialize serial port for "Serial Monitor"
|
|
// Initialise the TFT screen
|
|
tft.init();
|
|
|
|
rtc.setTime(0, 50, 21, 23, 5, 2023);
|
|
|
|
// =============== standby ===============
|
|
nsp32.Standby(0);
|
|
Serial.println("Standby");
|
|
tft.fillScreen(ILI9341_BLUE);
|
|
// =============== wakeup ===============
|
|
nsp32.Wakeup();
|
|
Serial.println("Wakeup");
|
|
tft.fillScreen(ILI9341_RED);
|
|
// =============== hello ===============
|
|
nsp32.Hello(0);
|
|
Serial.println("Hello");
|
|
tft.fillScreen(ILI9341_GREEN);
|
|
// =============== get sensor id ===============
|
|
|
|
Serial.println("e04");
|
|
tft.fillScreen(ILI9341_YELLOW);
|
|
|
|
|
|
char szSensorId[15]; // sensor id string buffer
|
|
nsp32.ExtractSensorIdStr(szSensorId); // now we have sensor id string in szSensorId[]
|
|
|
|
Serial.print(F("sensor id = "));
|
|
Serial.println(szSensorId);
|
|
|
|
// =============== get wavelength ===============
|
|
nsp32.GetWavelength(0);
|
|
|
|
WavelengthInfo infoW;
|
|
nsp32.ExtractWavelengthInfo(&infoW); // now we have all wavelength info in infoW, we can use e.g. "infoW.Wavelength" to access the wavelength data array
|
|
|
|
NOP = infoW.NumOfPoints;
|
|
|
|
Serial.printf("Number of points = %d\n", NOP);
|
|
|
|
Serial.println(F("Elements of wavelength = "));
|
|
for(int i = 0; i < NOP; i++){
|
|
Serial.printf("%d ",infoW.Wavelength[i]);
|
|
}
|
|
Serial.print("\n");
|
|
//**********************************************
|
|
//******************壓感*************************
|
|
|
|
pinMode(ADC_PIN,INPUT);
|
|
|
|
|
|
//**********************************************
|
|
|
|
|
|
// Set the rotation before we calibrate
|
|
tft.setRotation(0);
|
|
|
|
// Calibrate the touch screen and retrieve the scaling factors
|
|
touch_calibrate();
|
|
|
|
// Clear the screen
|
|
//tft.fillScreen(TFT_BLACK);
|
|
|
|
// Draw keypad
|
|
drawKeypad();
|
|
//顯示文字
|
|
tft.setTextSize(1);
|
|
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
tft.drawString("spectrum", 20, 200, 2);
|
|
|
|
tft.setTextSize(1);
|
|
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
tft.drawString("RESULT:", 5, 260, 4);
|
|
|
|
//示波視窗
|
|
tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK);
|
|
tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE);
|
|
//tft.drawFastVLine(DISP_X+DISP_W/2,DISP_Y,DISP_H, TFT_LIGHTGREY);
|
|
//tft.drawFastHLine(DISP_X,DISP_Y+DISP_H/2,DISP_W, TFT_LIGHTGREY);
|
|
|
|
|
|
}
|
|
//------------------------------------------------------------------------------------------
|
|
|
|
void loop(void) {
|
|
//顯示壓力
|
|
|
|
ADC_data=analogRead(ADC_PIN);
|
|
tft.setTextSize(1);
|
|
tft.setTextColor(TFT_WHITE, TFT_RED);
|
|
tft.drawString("FSR:", 10, 290, 2);
|
|
tft.setTextPadding(30);
|
|
tft.drawNumber( ADC_data, 50, 290, 2);
|
|
|
|
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
|
|
|
|
// Pressed will be set true is there is a valid touch on the screen
|
|
bool pressed = tft.getTouch(&t_x, &t_y);
|
|
|
|
// / Check if any key coordinate boxes contain the touch coordinates
|
|
//可按按鍵數
|
|
for (uint8_t b = 0; b < 3; b++) {
|
|
if (pressed && key[b].contains(t_x, t_y)) {
|
|
key[b].press(true); // tell the button it is pressed
|
|
} else {
|
|
key[b].press(false); // tell the button it is NOT pressed
|
|
}
|
|
}
|
|
// Check if any key has changed state
|
|
for (uint8_t b = 0; b < 3; b++) {
|
|
|
|
if (key[b].justReleased()) key[b].drawButton(); // draw normal
|
|
|
|
if (key[b].justPressed()) {
|
|
key[b].drawButton(true); // draw invert
|
|
|
|
// Del button, so delete last char 按鍵功能
|
|
|
|
if (b == 0) {
|
|
Serial.println("START");
|
|
}
|
|
|
|
if (b == 1) {
|
|
Serial.println("ON");
|
|
}
|
|
|
|
if (b == 2) {
|
|
Serial.println("DETECT");
|
|
}
|
|
|
|
delay(10); // UI debouncing
|
|
}
|
|
}
|
|
//*******************NSP32*************************
|
|
int timer = rtc.getSecond();
|
|
|
|
|
|
// =============== spectrum acquisition ===============
|
|
nsp32.AcqSpectrum(0, 32, 3, false); // integration time = 32; frame avg num = 3; disable AE
|
|
|
|
// "AcqSpectrum" command takes longer time to execute, the return packet is not immediately available
|
|
// when the acquisition is done, a "ready trigger" will fire, and nsp32.GetReturnPacketSize() will be > 0
|
|
while (nsp32.GetReturnPacketSize() <= 0) {
|
|
// TODO: can go to sleep, and wakeup when "ready trigger" interrupt occurs
|
|
|
|
nsp32.UpdateStatus(); // call UpdateStatus() to check async result
|
|
}
|
|
|
|
SpectrumInfo infoS;
|
|
nsp32.ExtractSpectrumInfo(&infoS); // now we have all spectrum info in infoW, we can use e.g. "infoS.Spectrum" to access the spectrum data array
|
|
|
|
Serial.println(F("Elements of spectrum = "));
|
|
for(int i = 0; i < NOP; i++){
|
|
Serial.printf("%.6f ", infoS.Spectrum[i], 6);
|
|
}
|
|
Serial.print("\n");
|
|
|
|
//counter++;
|
|
|
|
//Serial.printf("count: %d\n", counter);
|
|
|
|
Serial.print(rtc.getTime("%A, %B %d %Y %H:%M:%S:"));
|
|
Serial.println(rtc.getMillis());
|
|
|
|
//*************************************************
|
|
//示波
|
|
tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK);
|
|
tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE);
|
|
for(int x=0;x<60;x++){
|
|
double y = infoS.Spectrum[2*x]*2000;
|
|
//tft.drawFastVLine(x距, y距, 長度, TFT_LIGHTGREY);
|
|
tft.drawFastVLine(DISP_X+3*x, (DISP_Y+DISP_H)-y, y, TFT_RED);
|
|
tft.drawFastVLine(DISP_X+3*x+1, (DISP_Y+DISP_H)-y, y, TFT_GREEN);
|
|
tft.drawFastVLine(DISP_X+3*x+2, (DISP_Y+DISP_H)-y, y, TFT_BLUE);
|
|
tft.fillCircle(DISP_X+3*x+1, (DISP_Y+DISP_H)-y, 1, TFT_RED);
|
|
}
|
|
delay(2000);
|
|
}
|
|
//***************************************************
|
|
void touch_calibrate()
|
|
{
|
|
uint16_t calData[5];
|
|
uint8_t calDataOK = 0;
|
|
|
|
// check file system exists
|
|
if (!SPIFFS.begin()) {
|
|
Serial.println("Formating file system");
|
|
SPIFFS.format();
|
|
SPIFFS.begin();
|
|
}
|
|
|
|
// check if calibration file exists and size is correct
|
|
if (SPIFFS.exists(CALIBRATION_FILE)) {
|
|
if (REPEAT_CAL)
|
|
{
|
|
// Delete if we want to re-calibrate
|
|
SPIFFS.remove(CALIBRATION_FILE);
|
|
}
|
|
else
|
|
{
|
|
File f = SPIFFS.open(CALIBRATION_FILE, "r");
|
|
if (f) {
|
|
if (f.readBytes((char *)calData, 14) == 14)
|
|
calDataOK = 1;
|
|
f.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (calDataOK && !REPEAT_CAL) {
|
|
// calibration data valid
|
|
tft.setTouch(calData);
|
|
} else {
|
|
// data not valid so recalibrate
|
|
tft.fillScreen(TFT_BLACK);
|
|
tft.setCursor(20, 0);
|
|
tft.setTextFont(2);
|
|
tft.setTextSize(1);
|
|
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
|
|
tft.println("Touch corners as indicated");
|
|
|
|
tft.setTextFont(1);
|
|
tft.println();
|
|
|
|
if (REPEAT_CAL) {
|
|
tft.setTextColor(TFT_RED, TFT_BLACK);
|
|
tft.println("Set REPEAT_CAL to false to stop this running again!");
|
|
}
|
|
|
|
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
|
|
|
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
|
tft.println("Calibration complete!");
|
|
|
|
// store data
|
|
File f = SPIFFS.open(CALIBRATION_FILE, "w");
|
|
if (f) {
|
|
f.write((const unsigned char *)calData, 14);
|
|
f.close();
|
|
}
|
|
}
|
|
}
|
|
void drawKeypad()
|
|
{
|
|
// Draw the keys
|
|
for (uint8_t row = 0; row < 1; row++) {
|
|
for (uint8_t col = 0; col < 3; col++) {
|
|
uint8_t b = col + row * 3;
|
|
|
|
tft.setFreeFont(LABEL1_FONT);
|
|
|
|
|
|
key[b].initButton(&tft, KEY_X + col * (KEY_W + KEY_SPACING_X),
|
|
KEY_Y + row * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
|
|
KEY_W, KEY_H, TFT_WHITE, keyColor[b], TFT_WHITE,
|
|
keyLabel[b], KEY_TEXTSIZE);
|
|
key[b].drawButton();
|
|
}
|
|
}
|
|
}
|