[小專題]三合一復健球(未完成)
112.10.08
1.功能
2.程式介紹
#include <Arduino.h>
#include
<SoftwareSerial.h>
#include
<OLED.h>
enum TM7711_Mode
{
diff_10Hz = 1,
Temp = 2,
diff_40Hz = 3,
};
struct Press
{
uint8_t state;
int frep;
unsigned long startTime;
unsigned long countdownTime;
unsigned long diffTime;
};
struct ButtonData
{
bool isStart;
int time;
};
const uint8_t
Start_Button = 2;
const uint8_t
Time_Button = 3;
const uint8_t
Buzzer = 4;
const uint8_t
TM7711_SCK = 5;
const uint8_t
TM7711_DOUT = 6;
const uint8_t BT_RX
= 7;
const uint8_t BT_TX
= 8;
SoftwareSerial
BT(BT_RX, BT_TX);
OLED oled(128, 64);
const uint8_t
Mean_Size = 10;
uint8_t Mean_Count
= 0;
int
data[Mean_Size];
unsigned long
data_sum = 0;
const unsigned long
data_max = 1024;
const unsigned long
data_min = 0;
unsigned long
data_reference = 0;
unsigned long
oled_time = 0;
char *oled_num =
new char[10];
bool data_isUp =
false;
Press press;
ButtonData button;
char BT_data;
void Correction();
int
TM7711read(TM7711_Mode mode);
unsigned long
Averagefilter(int *buf, unsigned long bufmax, unsigned long bufmin);
void Pressjudge();
void
BuzzerMode(bool isStart);
void
OLED_display();
char *int2char(int
num);
void setup()
{
Serial.begin(9600);
// === OLED init ===
oled.begin();
oled.init(2, WHITE);
oled.print(0, 20,
"Initializing...", true);
// === TM7711 init ===
pinMode(TM7711_SCK, OUTPUT);
pinMode(TM7711_DOUT, INPUT);
Correction();
// === Button init ===
pinMode(Start_Button, INPUT);
pinMode(Time_Button, INPUT);
// === Buzzer init ===
pinMode(Buzzer, OUTPUT);
// === BT init ===
BT.begin(9600);
BT_data = 'n';
Serial.println("Initialized");
oled.clear();
oled.print(0, 20, "Initialized",
true);
delay(2000);
oled.clear();
oled.print(0, 20, "Time: 0min",
true);
}
void loop()
{
if (BT.available())
BT_data = BT.read();
if ((!digitalRead(Start_Button) || BT_data ==
'S') && !button.isStart && button.time)
{
oled.clear();
oled.print(0, 20,
"Initializing...", true);
Correction();
Correction();
button.isStart = true;
data_isUp = data_reference > 512 ? true
: false;
press.frep = 0;
press.state = 0;
BT_data = 'n';
BuzzerMode(true);
Serial.println("Start");
BT.print("S");
oled.clear();
oled.print(0, 20, "Start", true);
delay(2000);
press.diffTime = press.startTime =
oled_time = millis();
oled.init(1, WHITE);
OLED_display();
}
else if ((BT_data == '0' || BT_data == '1' ||
BT_data == '2' || BT_data == '3') && !button.isStart)
{
button.time = BT_data - '0';
press.countdownTime = button.time * 60000;
BT_data = 'n';
BuzzerMode(false);
Serial.print("Time: ");
Serial.print(button.time);
Serial.println("min");
oled.clear();
oled.print(0, 20, "Time: ",
false);
oled._print(OLED_char, 2,
int2char(button.time), "min");
oled.display();
delay(250);
}
else if ((!digitalRead(Time_Button))
&& !button.isStart)
{
button.time = (button.time + 1) % 4; // 0, 1, 2, 3
press.countdownTime = button.time * 60000;
// 0s, 60s, 120s, 240s
BT_data = 'n';
switch (button.time)
{
case 0:
BT.print("a");
break;
case
1:
BT.print("b");
break;
case 2:
BT.print("c");
break;
case 3:
BT.print("d");
break;
default:
break;
}
BuzzerMode(false);
Serial.print("Time: ");
Serial.print(button.time);
Serial.println("min");
oled.clear();
oled.print(0, 20, "Time: ",
false);
oled._print(OLED_char, 2,
int2char(button.time), "min");
oled.display();
delay(250);
}
if (!button.isStart || button.time == 0)
return;
if (millis() - press.startTime >=
press.countdownTime) // End
{
button.isStart = false;
Serial.println("End");
oled.clear();
BT.print(press.frep);
oled.init(2, WHITE);
oled.print(0, 20, "End", true);
delay(2000);
BT.print("E");
oled.clear();
oled.print(0, 20, "This time: ",
false);
oled._print(OLED_char, 2,
int2char(press.frep), "times");
oled.display();
BuzzerMode(true);
while (digitalRead(Start_Button))
yield();
oled.clear();
oled.print(0, 20, "Time: ",
false);
oled._print(OLED_char, 2,
int2char(button.time), "min");
oled.display();
delay(250);
}
data[Mean_Count] = TM7711read(diff_40Hz);
data_sum = Averagefilter(data, data_max,
data_min);
Mean_Count = (Mean_Count + 1) % Mean_Size;
Pressjudge();
Serial.print(data_reference);
Serial.print(" ");
Serial.print(data_sum);
Serial.print(" ");
Serial.println(press.frep);
if (millis() - oled_time > 1000 &&
button.isStart)
{
OLED_display();
oled_time = millis();
BT.print(press.frep);
}
delay(25);
}
void Correction()
{
data_sum = 0;
for (uint8_t i = 0; i < 50; i++)
{
data[Mean_Count] = TM7711read(diff_40Hz);
Mean_Count = (Mean_Count + 1) % Mean_Size;
if (i > 10)
data_sum += Averagefilter(data, data_max,
data_min);
delay(25);
}
data_reference = data_sum / 40;
Mean_Count = 0;
}
int
TM7711read(TM7711_Mode mode = diff_10Hz)
{
int buf = 0;
for (int i = 0; i < 24; i++)
{
digitalWrite(TM7711_SCK, HIGH);
buf <<= 1;
delayMicroseconds(5);
if (digitalRead(TM7711_DOUT))
buf |= 1;
digitalWrite(TM7711_SCK, LOW);
}
for (int i = 0; i < mode; i++)
{
digitalWrite(TM7711_SCK, HIGH);
delayMicroseconds(1);
digitalWrite(TM7711_SCK, LOW);
if (mode - i != 1)
delayMicroseconds(1);
}
return buf / 256;
}
unsigned long
Averagefilter(int *buf, unsigned long bufmax = 1024, unsigned long bufmin = 0)
{
unsigned long ret = 0;
for (int i = 0; i < Mean_Size; i++)
{
ret += buf[i];
}
ret /= Mean_Size;
ret = min(ret, bufmax);
ret = max(ret, bufmin);
return ret;
}
void Pressjudge()
{
if (!press.state && millis() -
press.diffTime > 750)
{
if (data_sum > data_reference +
data_reference * 0.75 && !data_isUp)
{
press.state = 1;
press.diffTime = millis();
}
else if (data_sum < data_reference -
data_reference * 0.75 && data_isUp)
{
press.state = 2;
press.diffTime = millis();
}
}
else if (press.state && millis() -
press.diffTime > 300)
{
if ((press.state == 1 && data_sum
> data_reference) &&
(press.state == 2 && data_sum
< data_reference))
return;
press.state = 0;
press.frep++;
press.diffTime = millis();
BuzzerMode(false);
}
}
void
BuzzerMode(bool isStart)
{
if (isStart)
{
tone(Buzzer, 1000, 200);
delay(200);
noTone(Buzzer);
tone(Buzzer, 1000, 200);
delay(200);
noTone(Buzzer);
}
else
{
tone(Buzzer, 1000, 200);
delay(200);
noTone(Buzzer);
}
}
void OLED_display()
{
oled.clear();
oled.print(0, 14, "Remaining time:
", false);
oled._print(OLED_char, 2,
int2char((press.countdownTime - (millis() - press.startTime)) / 1000),
"sec");
oled.print(0, 42, "Press: ",
false);
oled._print(OLED_char, 2,
int2char(press.frep), "times");
oled.display();
}
char *int2char(int
num)
{
sprintf(oled_num, "%d", num);
return oled_num;
}
沒有留言:
張貼留言