first commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"new": "cpp"
|
||||
}
|
||||
}
|
||||
72
include/drivers/AccelerometerController.h
Normal file
72
include/drivers/AccelerometerController.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef ADXL345_CONTROLLER_H
|
||||
#define ADXL345_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#define ADXL345_DEVID 0x00
|
||||
#define ADXL345_THRESH_TAP 0x1D
|
||||
#define ADXL345_OFSX 0x1E
|
||||
#define ADXL345_OFSY 0x1F
|
||||
#define ADXL345_OFSZ 0x20
|
||||
#define ADXL345_DUR 0x21
|
||||
#define ADXL345_LATENT 0x22
|
||||
#define ADXL345_WINDOW 0x23
|
||||
#define ADXL345_THRESH_ACT 0x24
|
||||
#define ADXL345_THRESH_INACT 0x25
|
||||
#define ADXL345_TIME_INACT 0x26
|
||||
#define ADXL345_ACT_INACT_CTL 0x27
|
||||
#define ADXL345_THRESH_FF 0x28
|
||||
#define ADXL345_TIME_FF 0x29
|
||||
#define ADXL345_TAP_AXES 0x2A
|
||||
#define ADXL345_ACT_TAP_STATUS 0x2B
|
||||
#define ADXL345_BW_RATE 0x2C
|
||||
#define ADXL345_POWER_CTL 0x2D
|
||||
#define ADXL345_INT_ENABLE 0x2E
|
||||
#define ADXL345_INT_MAP 0x2F
|
||||
#define ADXL345_INT_SOURCE 0x30
|
||||
#define ADXL345_DATA_FORMAT 0x31
|
||||
#define ADXL345_DATAX0 0x32
|
||||
#define ADXL345_DATAX1 0x33
|
||||
#define ADXL345_DATAY0 0x34
|
||||
#define ADXL345_DATAY1 0x35
|
||||
#define ADXL345_DATAZ0 0x36
|
||||
#define ADXL345_DATAZ1 0x37
|
||||
#define ADXL345_FIFO_CTL 0x38
|
||||
#define ADXL345_FIFO_STATUS 0x39
|
||||
|
||||
#define DEFAULT_MIN_READ_INTERVAL 50
|
||||
|
||||
class ADXL345Controller {
|
||||
private:
|
||||
uint8_t _deviceAddress;
|
||||
unsigned long _lastReadTime;
|
||||
unsigned long _minReadInterval;
|
||||
double _lastX;
|
||||
double _lastY;
|
||||
double _lastZ;
|
||||
bool _lastReadSuccess;
|
||||
|
||||
void setRegister(uint8_t reg, uint8_t value);
|
||||
uint8_t readRegister(uint8_t reg);
|
||||
void readRegisters(uint8_t reg, uint8_t count, uint8_t *buffer);
|
||||
|
||||
public:
|
||||
ADXL345Controller(uint8_t deviceAddress = 0x53);
|
||||
|
||||
void begin();
|
||||
|
||||
bool read();
|
||||
|
||||
double getX();
|
||||
double getY();
|
||||
double getZ();
|
||||
|
||||
bool isLastReadSuccessful() const;
|
||||
void setMinReadInterval(unsigned long interval);
|
||||
void setRange(uint8_t range);
|
||||
void setDataRate(uint8_t rate);
|
||||
void setOffsets(int8_t xOffset, int8_t yOffset, int8_t zOffset);
|
||||
};
|
||||
|
||||
#endif
|
||||
21
include/drivers/ButtonController.h
Normal file
21
include/drivers/ButtonController.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef BUTTON_CONTROLLER_H
|
||||
#define BUTTON_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class ButtonController {
|
||||
private:
|
||||
const int _buttonPin;
|
||||
unsigned long _lastDebounceTime;
|
||||
unsigned long _debounceDelay;
|
||||
bool _lastButtonState;
|
||||
bool _buttonState;
|
||||
|
||||
public:
|
||||
ButtonController(int buttonPin, unsigned long debounceDelay = 50);
|
||||
bool wasOn();
|
||||
void tick();
|
||||
bool getState() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
27
include/drivers/DHTController.h
Normal file
27
include/drivers/DHTController.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef DHT_CONTROLLER_H
|
||||
#define DHT_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <DHT.h>
|
||||
|
||||
class DHTController {
|
||||
private:
|
||||
DHT _dht;
|
||||
unsigned long _lastReadTime;
|
||||
unsigned long _minReadInterval;
|
||||
float _lastTemperature;
|
||||
float _lastHumidity;
|
||||
bool _lastReadSuccess;
|
||||
|
||||
public:
|
||||
DHTController(uint8_t pin, uint8_t type = DHT11);
|
||||
|
||||
void begin();
|
||||
bool read();
|
||||
float getTemperature();
|
||||
float getHumidity();
|
||||
bool isLastReadSuccessful() const;
|
||||
void setMinReadInterval(unsigned long interval);
|
||||
};
|
||||
|
||||
#endif
|
||||
37
include/drivers/DistanceSensorController.h
Normal file
37
include/drivers/DistanceSensorController.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef DISTANCE_SENSOR_CONTROLLER_H
|
||||
#define DISTANCE_SENSOR_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define DEFAULT_MIN_READ_INTERVAL_DIST 100
|
||||
#define DEFAULT_SAMPLES 3
|
||||
#define MAX_DISTANCE 400
|
||||
|
||||
class DistanceSensorController {
|
||||
private:
|
||||
uint8_t _trigPin;
|
||||
uint8_t _echoPin;
|
||||
unsigned long _lastReadTime;
|
||||
unsigned long _minReadInterval;
|
||||
long _lastDistanceCm;
|
||||
bool _lastReadSuccess;
|
||||
uint8_t _numSamples;
|
||||
unsigned long _timeout;
|
||||
|
||||
long microsecondsToCentimeters(long microseconds);
|
||||
|
||||
long takeMeasurement();
|
||||
|
||||
public:
|
||||
DistanceSensorController(uint8_t trigPin, uint8_t echoPin);
|
||||
void begin();
|
||||
bool read();
|
||||
long getDistanceCm();
|
||||
long getDistanceInch();
|
||||
bool isLastReadSuccessful() const;
|
||||
void setMinReadInterval(unsigned long interval);
|
||||
void setNumSamples(uint8_t samples);
|
||||
void setTimeout(unsigned long timeout);
|
||||
};
|
||||
|
||||
#endif
|
||||
68
include/drivers/JoystickController.h
Normal file
68
include/drivers/JoystickController.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef JOYSTICK_H
|
||||
#define JOYSTICK_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
enum JoystickDirection {
|
||||
CENTER,
|
||||
UP,
|
||||
UP_RIGHT,
|
||||
RIGHT,
|
||||
DOWN_RIGHT,
|
||||
DOWN,
|
||||
DOWN_LEFT,
|
||||
LEFT,
|
||||
UP_LEFT
|
||||
};
|
||||
|
||||
class JoystickController {
|
||||
private:
|
||||
uint8_t pinX;
|
||||
uint8_t pinY;
|
||||
uint8_t pinButton;
|
||||
|
||||
int centerX;
|
||||
int centerY;
|
||||
|
||||
int rawX;
|
||||
int rawY;
|
||||
bool buttonState;
|
||||
|
||||
int deadzone;
|
||||
int debounceDelay;
|
||||
unsigned long lastDebounceTime;
|
||||
|
||||
int lastX;
|
||||
int lastY;
|
||||
bool lastButtonState;
|
||||
|
||||
void readRawValues();
|
||||
|
||||
static JoystickController* _instance;
|
||||
|
||||
public:
|
||||
JoystickController(uint8_t xPin, uint8_t yPin, uint8_t buttonPin = 255);
|
||||
~JoystickController();
|
||||
|
||||
void begin();
|
||||
void calibrate();
|
||||
void setDeadzone(int value);
|
||||
void setDebounceDelay(int delayMs);
|
||||
void tick();
|
||||
|
||||
int getRawX();
|
||||
int getRawY();
|
||||
int getX();
|
||||
int getY();
|
||||
int getOffsetX();
|
||||
int getOffsetY();
|
||||
|
||||
bool isPressed();
|
||||
bool isCentered();
|
||||
|
||||
JoystickDirection getDirection();
|
||||
String getDirectionString();
|
||||
int getDistancePercent();
|
||||
};
|
||||
|
||||
#endif
|
||||
34
include/drivers/LCDController.h
Normal file
34
include/drivers/LCDController.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef LCD_CONTROLLER_H
|
||||
#define LCD_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdio.h>
|
||||
#include <LiquidCrystal.h>
|
||||
#include "LEDController.h"
|
||||
|
||||
class LCDController {
|
||||
private:
|
||||
FILE* _lcdOutput;
|
||||
LiquidCrystal* _lcd;
|
||||
int _lcdCols;
|
||||
int _lcdRows;
|
||||
int _cursorRow;
|
||||
int _cursorCol;
|
||||
|
||||
static int lcdPutchar(char c, FILE* stream);
|
||||
static LCDController* _instance;
|
||||
|
||||
public:
|
||||
LCDController(uint8_t rs, uint8_t enable, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
|
||||
int cols = 16, int rows = 2);
|
||||
~LCDController();
|
||||
void begin();
|
||||
FILE* stream();
|
||||
void clear();
|
||||
void setCursor(int col, int row);
|
||||
void print(const char* text);
|
||||
|
||||
static LCDController* getInstance() { return _instance; }
|
||||
};
|
||||
|
||||
#endif
|
||||
31
include/drivers/LEDController.h
Normal file
31
include/drivers/LEDController.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef LED_CONTROLLER_H
|
||||
#define LED_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class LEDController {
|
||||
private:
|
||||
const int _ledPin;
|
||||
bool _state;
|
||||
bool _isBlinking;
|
||||
unsigned long _previousMillis;
|
||||
unsigned long _blinkInterval;
|
||||
unsigned long _blinkCount;
|
||||
|
||||
public:
|
||||
LEDController(int ledPin);
|
||||
LEDController(int ledPin, bool state);
|
||||
void turnOn();
|
||||
void turnOff();
|
||||
void toggle();
|
||||
bool getState() const;
|
||||
void blink(bool enable);
|
||||
bool isBlinkingEnabled() const;
|
||||
void interval(unsigned long interval);
|
||||
unsigned long getBlinkInterval() const;
|
||||
unsigned long getBlinkCount() const;
|
||||
void tick();
|
||||
void set(bool value);
|
||||
};
|
||||
|
||||
#endif
|
||||
24
include/drivers/MotorController.h
Normal file
24
include/drivers/MotorController.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef DC_MOTOR_DRIVER_H
|
||||
#define DC_MOTOR_DRIVER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class MotorController {
|
||||
private:
|
||||
const int _pinIA;
|
||||
const int _pinIB;
|
||||
int _currentPower;
|
||||
|
||||
void applyPower();
|
||||
|
||||
public:
|
||||
MotorController(int pinIA, int pinIB);
|
||||
void set(int power);
|
||||
void stop();
|
||||
void maximum();
|
||||
void inc();
|
||||
void dec();
|
||||
int getPower() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
0
include/drivers/PassiveBuzzerController.h
Normal file
0
include/drivers/PassiveBuzzerController.h
Normal file
35
include/drivers/PhotoresistorController.h
Normal file
35
include/drivers/PhotoresistorController.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef PHOTORESISTOR_CONTROLLER_H
|
||||
#define PHOTORESISTOR_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define DEFAULT_MIN_READ_INTERVAL 50
|
||||
#define DEFAULT_SAMPLES 3
|
||||
|
||||
class PhotoresistorController {
|
||||
private:
|
||||
uint8_t _pin;
|
||||
unsigned long _lastReadTime;
|
||||
unsigned long _minReadInterval;
|
||||
int _lastRawValue;
|
||||
int _lastPercentValue;
|
||||
bool _lastReadSuccess;
|
||||
uint8_t _numSamples;
|
||||
int _maxValue;
|
||||
int _minValue;
|
||||
|
||||
public:
|
||||
PhotoresistorController(uint8_t pin, int minValue = 0, int maxValue = 1023);
|
||||
void begin();
|
||||
bool read();
|
||||
int getRawValue();
|
||||
int getPercentValue();
|
||||
void calibrate(int minValue, int maxValue);
|
||||
void autoCalibrateDark();
|
||||
void autoCalibrateBright();
|
||||
bool isLastReadSuccessful() const;
|
||||
void setMinReadInterval(unsigned long interval);
|
||||
void setNumSamples(uint8_t samples);
|
||||
};
|
||||
|
||||
#endif
|
||||
0
include/drivers/RGBLEDController.h
Normal file
0
include/drivers/RGBLEDController.h
Normal file
38
include/drivers/RelayController.h
Normal file
38
include/drivers/RelayController.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef RELAY_CONTROLLER_H
|
||||
#define RELAY_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class RelayController {
|
||||
private:
|
||||
const int _relayPin;
|
||||
bool _isConnected;
|
||||
|
||||
public:
|
||||
RelayController(int relayPin) :
|
||||
_relayPin(relayPin),
|
||||
_isConnected(false) {
|
||||
pinMode(_relayPin, OUTPUT);
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void connect() {
|
||||
digitalWrite(_relayPin, LOW);
|
||||
_isConnected = true;
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
digitalWrite(_relayPin, HIGH);
|
||||
_isConnected = false;
|
||||
}
|
||||
|
||||
bool isConnected() const {
|
||||
return _isConnected;
|
||||
}
|
||||
|
||||
int getPin() const {
|
||||
return _relayPin;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
54
include/drivers/ThermistorController.h
Normal file
54
include/drivers/ThermistorController.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef THERMISTOR_CONTROLLER_H
|
||||
#define THERMISTOR_CONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class ThermistorController {
|
||||
private:
|
||||
const int _thermistorPin;
|
||||
const float _seriesResistor;
|
||||
const float _bParameter;
|
||||
const float _nominalTemp;
|
||||
|
||||
static const int _bufferSize = 10;
|
||||
float _rawReadings[_bufferSize];
|
||||
int _bufferIndex;
|
||||
bool _bufferFilled;
|
||||
|
||||
float _filteredRaw;
|
||||
float _smoothedRaw;
|
||||
float _resistance;
|
||||
float _temperatureC;
|
||||
|
||||
const float _weights[_bufferSize] = {0.05, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.15, 0.15, 0.2};
|
||||
|
||||
const float _minTemp;
|
||||
const float _maxTemp;
|
||||
|
||||
float applySaltPepperFilter();
|
||||
float applyWeightedMovingAverage();
|
||||
float calculateResistance(float adcValue);
|
||||
float calculateTemperature(float resistance);
|
||||
float applySaturation(float value, float min, float max);
|
||||
|
||||
public:
|
||||
ThermistorController(
|
||||
int thermistorPin,
|
||||
float seriesResistor = 10000.0,
|
||||
float bParameter = 3435.0,
|
||||
float nominalTemp = 25.0,
|
||||
float minTemp = -55.0,
|
||||
float maxTemp = 125.0
|
||||
);
|
||||
|
||||
void update();
|
||||
|
||||
float getRawValue() const;
|
||||
float getFilteredRaw() const;
|
||||
float getSmoothedRaw() const;
|
||||
float getResistance() const;
|
||||
float getTemperatureC() const;
|
||||
float getTemperatureF() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
include/labs/Lab2_1.h
Normal file
24
include/labs/Lab2_1.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef LAB2_1_H
|
||||
#define LAB2_1_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LEDController.h"
|
||||
#include "drivers/ButtonController.h"
|
||||
#include "drivers/LCDController.h"
|
||||
|
||||
#define BUTTON_TOGGLE_PIN 13
|
||||
#define BUTTON_INCREMENT_PIN 11
|
||||
#define BUTTON_DECREMENT_PIN 12
|
||||
#define LED_PIN 22
|
||||
#define LED_BLINK_PIN 24
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
|
||||
void Lab2_1Task(void* pv);
|
||||
|
||||
#endif
|
||||
33
include/labs/Lab2_2.h
Normal file
33
include/labs/Lab2_2.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef LAB2_2_H
|
||||
#define LAB2_2_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
#include <queue.h>
|
||||
#include "drivers/LEDController.h"
|
||||
#include "drivers/ButtonController.h"
|
||||
#include "drivers/LCDController.h"
|
||||
|
||||
#define LED_BUTTON_PIN 28
|
||||
#define LED_BLINK_PIN 24
|
||||
#define BUTTON_PIN 13
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
|
||||
typedef struct {
|
||||
ButtonController* button;
|
||||
LEDController* led;
|
||||
LEDController* blinkLed;
|
||||
LCDController* lcd;
|
||||
SemaphoreHandle_t buttonSemaphore;
|
||||
QueueHandle_t dataQueue;
|
||||
} TaskParameters;
|
||||
|
||||
void Lab2_2Task(void* pv);
|
||||
|
||||
#endif
|
||||
33
include/labs/Lab3_1.h
Normal file
33
include/labs/Lab3_1.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef LAB3_1_H
|
||||
#define LAB3_1_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LCDController.h"
|
||||
#include "drivers/JoystickController.h"
|
||||
#include "drivers/DHTController.h"
|
||||
#include "drivers/AccelerometerController.h"
|
||||
#include "drivers/PhotoresistorController.h"
|
||||
#include "drivers/DistanceSensorController.h"
|
||||
|
||||
#define VRX A0
|
||||
#define VRY A1
|
||||
#define SW 15
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
#define DHT_PIN 4
|
||||
#define PHOTORESISTOR_PIN A3
|
||||
#define TRIG_PIN 5
|
||||
#define ECHO_PIN 6
|
||||
|
||||
void Lab3_1Task(void* pv);
|
||||
void DHTTask(void* pv);
|
||||
void AccelerometerTask(void* pv);
|
||||
void PhotoresistorTask(void*pv);
|
||||
void DistanceTask(void* pv);
|
||||
|
||||
#endif
|
||||
19
include/labs/Lab3_2.h
Normal file
19
include/labs/Lab3_2.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef LAB3_2_H
|
||||
#define LAB3_2_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LCDController.h"
|
||||
#include "drivers/ThermistorController.h"
|
||||
|
||||
#define THERMISTOR_PIN A2
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
|
||||
void Lab3_2Task(void* pv);
|
||||
|
||||
#endif
|
||||
23
include/labs/Lab4_1.h
Normal file
23
include/labs/Lab4_1.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef LAB4_1_H
|
||||
#define LAB4_1_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LCDController.h"
|
||||
#include "drivers/JoystickController.h"
|
||||
#include "drivers/RelayController.h"
|
||||
|
||||
#define VRX A0
|
||||
#define VRY A1
|
||||
#define SW 15
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
#define RELAY_PIN 14
|
||||
|
||||
void Lab4_1Task(void* pv);
|
||||
|
||||
#endif
|
||||
26
include/labs/Lab4_2.h
Normal file
26
include/labs/Lab4_2.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef LAB4_2_H
|
||||
#define LAB4_2_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LCDController.h"
|
||||
#include "drivers/JoystickController.h"
|
||||
#include "drivers/RelayController.h"
|
||||
#include "drivers/MotorController.h"
|
||||
|
||||
#define MOTOR_PIN_IA 2
|
||||
#define MOTOR_PIN_IB 3
|
||||
#define RELAY_PIN 14
|
||||
#define VRX A0
|
||||
#define VRY A1
|
||||
#define SW 15
|
||||
#define RS 31
|
||||
#define EN 33
|
||||
#define D4 35
|
||||
#define D5 37
|
||||
#define D6 39
|
||||
#define D7 41
|
||||
|
||||
void Lab4_2Task(void* pv);
|
||||
|
||||
#endif
|
||||
21
include/labs/LabSelector.h
Normal file
21
include/labs/LabSelector.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef LABSELECTOR_H
|
||||
#define LABSELECTOR_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
#include "drivers/LCDController.h"
|
||||
#include "drivers/JoystickController.h"
|
||||
#include "Lab2_1.h"
|
||||
#include "Lab2_2.h"
|
||||
#include "Lab3_1.h"
|
||||
#include "Lab3_2.h"
|
||||
#include "Lab4_1.h"
|
||||
#include "Lab4_2.h"
|
||||
|
||||
#define VRX A0
|
||||
#define VRY A1
|
||||
#define SW 15
|
||||
|
||||
void LabSelectorTask(void* pv);
|
||||
|
||||
#endif
|
||||
19
platformio.ini
Normal file
19
platformio.ini
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:megaatmega2560]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
adafruit/DHT sensor library@^1.4.6
|
||||
feilipu/FreeRTOS@^10.5.1-0
|
||||
arduino-libraries/LiquidCrystal@^1.0.7
|
||||
130
src/drivers/AccelerometerController.cpp
Normal file
130
src/drivers/AccelerometerController.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "drivers/AccelerometerController.h"
|
||||
|
||||
ADXL345Controller::ADXL345Controller(uint8_t deviceAddress) :
|
||||
_deviceAddress(deviceAddress),
|
||||
_lastReadTime(0),
|
||||
_minReadInterval(DEFAULT_MIN_READ_INTERVAL),
|
||||
_lastX(0.0),
|
||||
_lastY(0.0),
|
||||
_lastZ(0.0),
|
||||
_lastReadSuccess(false) {
|
||||
}
|
||||
|
||||
void ADXL345Controller::begin() {
|
||||
Wire.begin();
|
||||
|
||||
uint8_t deviceID = readRegister(ADXL345_DEVID);
|
||||
if (deviceID != 0xE5) {
|
||||
_lastReadSuccess = false;
|
||||
return;
|
||||
}
|
||||
|
||||
setRegister(ADXL345_POWER_CTL, 0x08);
|
||||
|
||||
setRegister(ADXL345_DATA_FORMAT, 0x0B);
|
||||
|
||||
setRegister(ADXL345_BW_RATE, 0x0A);
|
||||
|
||||
setRegister(ADXL345_OFSX, 0x00);
|
||||
setRegister(ADXL345_OFSY, 0x00);
|
||||
setRegister(ADXL345_OFSZ, 0x00);
|
||||
|
||||
_lastReadSuccess = true;
|
||||
}
|
||||
|
||||
bool ADXL345Controller::read() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
if (currentTime - _lastReadTime >= _minReadInterval) {
|
||||
_lastReadTime = currentTime;
|
||||
|
||||
uint8_t buffer[6];
|
||||
readRegisters(ADXL345_DATAX0, 6, buffer);
|
||||
|
||||
int16_t x = ((int16_t)buffer[1] << 8) | buffer[0];
|
||||
int16_t y = ((int16_t)buffer[3] << 8) | buffer[2];
|
||||
int16_t z = ((int16_t)buffer[5] << 8) | buffer[4];
|
||||
|
||||
_lastX = x / 256.0;
|
||||
_lastY = y / 256.0;
|
||||
_lastZ = z / 256.0;
|
||||
|
||||
_lastReadSuccess = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
double ADXL345Controller::getX() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastX;
|
||||
}
|
||||
|
||||
double ADXL345Controller::getY() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastY;
|
||||
}
|
||||
|
||||
double ADXL345Controller::getZ() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastZ;
|
||||
}
|
||||
|
||||
bool ADXL345Controller::isLastReadSuccessful() const {
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
void ADXL345Controller::setMinReadInterval(unsigned long interval) {
|
||||
_minReadInterval = interval;
|
||||
}
|
||||
|
||||
void ADXL345Controller::setRange(uint8_t range) {
|
||||
uint8_t format = readRegister(ADXL345_DATA_FORMAT);
|
||||
|
||||
format &= ~0x03;
|
||||
|
||||
if (range > 3) range = 3;
|
||||
format |= range;
|
||||
|
||||
setRegister(ADXL345_DATA_FORMAT, format);
|
||||
}
|
||||
|
||||
void ADXL345Controller::setDataRate(uint8_t rate) {
|
||||
if (rate > 15) rate = 15;
|
||||
|
||||
setRegister(ADXL345_BW_RATE, rate);
|
||||
}
|
||||
|
||||
void ADXL345Controller::setOffsets(int8_t xOffset, int8_t yOffset, int8_t zOffset) {
|
||||
setRegister(ADXL345_OFSX, xOffset);
|
||||
setRegister(ADXL345_OFSY, yOffset);
|
||||
setRegister(ADXL345_OFSZ, zOffset);
|
||||
}
|
||||
|
||||
void ADXL345Controller::setRegister(uint8_t reg, uint8_t value) {
|
||||
Wire.beginTransmission(_deviceAddress);
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t ADXL345Controller::readRegister(uint8_t reg) {
|
||||
Wire.beginTransmission(_deviceAddress);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(_deviceAddress, (uint8_t)1);
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
void ADXL345Controller::readRegisters(uint8_t reg, uint8_t count, uint8_t *buffer) {
|
||||
Wire.beginTransmission(_deviceAddress);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(_deviceAddress, count);
|
||||
for (uint8_t i = 0; i < count && Wire.available(); i++) {
|
||||
buffer[i] = Wire.read();
|
||||
}
|
||||
}
|
||||
44
src/drivers/ButtonController.cpp
Normal file
44
src/drivers/ButtonController.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "drivers/ButtonController.h"
|
||||
|
||||
ButtonController::ButtonController(int buttonPin, unsigned long debounceDelay) :
|
||||
_buttonPin(buttonPin),
|
||||
_lastDebounceTime(0),
|
||||
_debounceDelay(debounceDelay),
|
||||
_lastButtonState(HIGH),
|
||||
_buttonState(HIGH) {
|
||||
|
||||
pinMode(_buttonPin, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
bool ButtonController::wasOn() {
|
||||
bool result = false;
|
||||
int reading = digitalRead(_buttonPin);
|
||||
|
||||
if (reading != _lastButtonState) _lastDebounceTime = millis();
|
||||
|
||||
if ((millis() - _lastDebounceTime) > _debounceDelay) {
|
||||
if (reading != _buttonState) {
|
||||
_buttonState = reading;
|
||||
if (_buttonState == LOW) result = true;
|
||||
}
|
||||
}
|
||||
|
||||
_lastButtonState = reading;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ButtonController::tick() {
|
||||
int reading = digitalRead(_buttonPin);
|
||||
|
||||
if (reading != _lastButtonState) _lastDebounceTime = millis();
|
||||
|
||||
if ((millis() - _lastDebounceTime) > _debounceDelay)
|
||||
if (reading != _buttonState) _buttonState = reading;
|
||||
|
||||
_lastButtonState = reading;
|
||||
}
|
||||
|
||||
bool ButtonController::getState() const {
|
||||
return _buttonState;
|
||||
}
|
||||
58
src/drivers/DHTController.cpp
Normal file
58
src/drivers/DHTController.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "drivers/DHTController.h"
|
||||
|
||||
#define DEFAULT_MIN_READ_INTERVAL 2000
|
||||
|
||||
DHTController::DHTController(uint8_t pin, uint8_t type) :
|
||||
_dht(pin, type),
|
||||
_lastReadTime(0),
|
||||
_minReadInterval(DEFAULT_MIN_READ_INTERVAL),
|
||||
_lastTemperature(0.0f),
|
||||
_lastHumidity(0.0f),
|
||||
_lastReadSuccess(false) {
|
||||
}
|
||||
|
||||
void DHTController::begin() {
|
||||
_dht.begin();
|
||||
}
|
||||
|
||||
bool DHTController::read() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
if (currentTime - _lastReadTime >= _minReadInterval) {
|
||||
_lastReadTime = currentTime;
|
||||
|
||||
float humidity = _dht.readHumidity();
|
||||
|
||||
float temperature = _dht.readTemperature();
|
||||
|
||||
if (isnan(humidity) || isnan(temperature)) {
|
||||
_lastReadSuccess = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_lastHumidity = humidity;
|
||||
_lastTemperature = temperature;
|
||||
_lastReadSuccess = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
float DHTController::getTemperature() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastTemperature;
|
||||
}
|
||||
|
||||
float DHTController::getHumidity() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastHumidity;
|
||||
}
|
||||
|
||||
bool DHTController::isLastReadSuccessful() const {
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
void DHTController::setMinReadInterval(unsigned long interval) {
|
||||
_minReadInterval = interval;
|
||||
}
|
||||
99
src/drivers/DistanceSensorController.cpp
Normal file
99
src/drivers/DistanceSensorController.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "drivers/DistanceSensorController.h"
|
||||
|
||||
DistanceSensorController::DistanceSensorController(uint8_t trigPin, uint8_t echoPin) :
|
||||
_trigPin(trigPin),
|
||||
_echoPin(echoPin),
|
||||
_lastReadTime(0),
|
||||
_minReadInterval(DEFAULT_MIN_READ_INTERVAL_DIST),
|
||||
_lastDistanceCm(0),
|
||||
_lastReadSuccess(false),
|
||||
_numSamples(DEFAULT_SAMPLES),
|
||||
_timeout(30000) {
|
||||
}
|
||||
|
||||
void DistanceSensorController::begin() {
|
||||
pinMode(_trigPin, OUTPUT);
|
||||
pinMode(_echoPin, INPUT);
|
||||
_lastReadSuccess = true;
|
||||
}
|
||||
|
||||
bool DistanceSensorController::read() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
if (currentTime - _lastReadTime >= _minReadInterval) {
|
||||
_lastReadTime = currentTime;
|
||||
|
||||
long sum = 0;
|
||||
int validSamples = 0;
|
||||
|
||||
for (uint8_t i = 0; i < _numSamples; i++) {
|
||||
long measurement = takeMeasurement();
|
||||
|
||||
if (measurement > 0 && measurement < MAX_DISTANCE) {
|
||||
sum += measurement;
|
||||
validSamples++;
|
||||
}
|
||||
|
||||
if (_numSamples > 1) {
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
if (validSamples > 0) {
|
||||
_lastDistanceCm = sum / validSamples;
|
||||
_lastReadSuccess = true;
|
||||
} else {
|
||||
_lastReadSuccess = false;
|
||||
}
|
||||
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
long DistanceSensorController::takeMeasurement() {
|
||||
digitalWrite(_trigPin, LOW);
|
||||
delayMicroseconds(2);
|
||||
|
||||
digitalWrite(_trigPin, HIGH);
|
||||
delayMicroseconds(10);
|
||||
digitalWrite(_trigPin, LOW);
|
||||
|
||||
long duration = pulseIn(_echoPin, HIGH, _timeout);
|
||||
|
||||
return microsecondsToCentimeters(duration);
|
||||
}
|
||||
|
||||
long DistanceSensorController::microsecondsToCentimeters(long microseconds) {
|
||||
if (microseconds == 0) return 0;
|
||||
return microseconds / 29 / 2;
|
||||
}
|
||||
|
||||
long DistanceSensorController::getDistanceCm() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastDistanceCm;
|
||||
}
|
||||
|
||||
long DistanceSensorController::getDistanceInch() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastDistanceCm / 2.54;
|
||||
}
|
||||
|
||||
bool DistanceSensorController::isLastReadSuccessful() const {
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
void DistanceSensorController::setMinReadInterval(unsigned long interval) {
|
||||
_minReadInterval = interval;
|
||||
}
|
||||
|
||||
void DistanceSensorController::setNumSamples(uint8_t samples) {
|
||||
if (samples > 0) {
|
||||
_numSamples = samples;
|
||||
}
|
||||
}
|
||||
|
||||
void DistanceSensorController::setTimeout(unsigned long timeout) {
|
||||
_timeout = timeout;
|
||||
}
|
||||
177
src/drivers/JoystickController.cpp
Normal file
177
src/drivers/JoystickController.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
#include "drivers/JoystickController.h"
|
||||
|
||||
JoystickController* JoystickController::_instance = nullptr;
|
||||
|
||||
JoystickController::JoystickController(uint8_t xPin, uint8_t yPin, uint8_t buttonPin) {
|
||||
pinX = xPin;
|
||||
pinY = yPin;
|
||||
pinButton = buttonPin;
|
||||
|
||||
centerX = 512;
|
||||
centerY = 512;
|
||||
deadzone = 100;
|
||||
debounceDelay = 10;
|
||||
lastDebounceTime = 0;
|
||||
|
||||
lastX = centerX;
|
||||
lastY = centerY;
|
||||
lastButtonState = false;
|
||||
|
||||
pinMode(pinX, INPUT);
|
||||
pinMode(pinY, INPUT);
|
||||
|
||||
if (pinButton != 255) {
|
||||
pinMode(pinButton, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
_instance = this;
|
||||
|
||||
calibrate();
|
||||
}
|
||||
|
||||
JoystickController::~JoystickController() {
|
||||
if (_instance == this) _instance = nullptr;
|
||||
}
|
||||
|
||||
void JoystickController::readRawValues() {
|
||||
rawX = analogRead(pinX);
|
||||
rawY = analogRead(pinY);
|
||||
|
||||
if (pinButton != 255) {
|
||||
buttonState = !digitalRead(pinButton);
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickController::begin() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
readRawValues();
|
||||
delay(5);
|
||||
}
|
||||
|
||||
calibrate();
|
||||
}
|
||||
|
||||
void JoystickController::calibrate() {
|
||||
int sumX = 0;
|
||||
int sumY = 0;
|
||||
const int samples = 20;
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
readRawValues();
|
||||
sumX += rawX;
|
||||
sumY += rawY;
|
||||
delay(5);
|
||||
}
|
||||
|
||||
centerX = sumX / samples;
|
||||
centerY = sumY / samples;
|
||||
|
||||
lastX = centerX;
|
||||
lastY = centerY;
|
||||
}
|
||||
|
||||
void JoystickController::setDeadzone(int value) {
|
||||
deadzone = constrain(value, 0, 512);
|
||||
}
|
||||
|
||||
void JoystickController::setDebounceDelay(int delayMs) {
|
||||
debounceDelay = delayMs;
|
||||
}
|
||||
|
||||
void JoystickController::tick() {
|
||||
readRawValues();
|
||||
|
||||
if ((millis() - lastDebounceTime) > debounceDelay) {
|
||||
if (abs(rawX - lastX) > deadzone || abs(rawY - lastY) > deadzone || buttonState != lastButtonState) {
|
||||
lastX = rawX;
|
||||
lastY = rawY;
|
||||
lastButtonState = buttonState;
|
||||
lastDebounceTime = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int JoystickController::getRawX() {
|
||||
return rawX;
|
||||
}
|
||||
|
||||
int JoystickController::getRawY() {
|
||||
return rawY;
|
||||
}
|
||||
|
||||
int JoystickController::getX() {
|
||||
return lastX;
|
||||
}
|
||||
|
||||
int JoystickController::getY() {
|
||||
return lastY;
|
||||
}
|
||||
|
||||
int JoystickController::getOffsetX() {
|
||||
return lastX - centerX;
|
||||
}
|
||||
|
||||
int JoystickController::getOffsetY() {
|
||||
return lastY - centerY;
|
||||
}
|
||||
|
||||
bool JoystickController::isPressed() {
|
||||
return lastButtonState;
|
||||
}
|
||||
|
||||
bool JoystickController::isCentered() {
|
||||
return (abs(lastX - centerX) <= deadzone && abs(lastY - centerY) <= deadzone);
|
||||
}
|
||||
|
||||
JoystickDirection JoystickController::getDirection() {
|
||||
int dx = lastX - centerX;
|
||||
int dy = lastY - centerY;
|
||||
|
||||
if (abs(dx) <= deadzone && abs(dy) <= deadzone) {
|
||||
return CENTER;
|
||||
}
|
||||
|
||||
float angle = atan2(-dy, dx) * 180 / PI;
|
||||
|
||||
float adjusted = angle + 22.5;
|
||||
if (adjusted < 0) adjusted += 360;
|
||||
|
||||
int sector = int(adjusted / 45) % 8;
|
||||
|
||||
switch (sector) {
|
||||
case 0: return RIGHT;
|
||||
case 1: return UP_RIGHT;
|
||||
case 2: return UP;
|
||||
case 3: return UP_LEFT;
|
||||
case 4: return LEFT;
|
||||
case 5: return DOWN_LEFT;
|
||||
case 6: return DOWN;
|
||||
case 7: return DOWN_RIGHT;
|
||||
default: return CENTER;
|
||||
}
|
||||
}
|
||||
|
||||
String JoystickController::getDirectionString() {
|
||||
JoystickDirection dir = getDirection();
|
||||
|
||||
switch (dir) {
|
||||
case CENTER: return "CENTER";
|
||||
case UP: return "UP";
|
||||
case UP_RIGHT: return "UP_RIGHT";
|
||||
case RIGHT: return "RIGHT";
|
||||
case DOWN_RIGHT:return "DOWN_RIGHT";
|
||||
case DOWN: return "DOWN";
|
||||
case DOWN_LEFT: return "DOWN_LEFT";
|
||||
case LEFT: return "LEFT";
|
||||
case UP_LEFT: return "UP_LEFT";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
int JoystickController::getDistancePercent() {
|
||||
int dx = lastX - centerX;
|
||||
int dy = lastY - centerY;
|
||||
float distance = sqrt(dx*dx + dy*dy);
|
||||
|
||||
return constrain(map(distance, deadzone, 512, 0, 100), 0, 100);
|
||||
}
|
||||
89
src/drivers/LCDController.cpp
Normal file
89
src/drivers/LCDController.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "drivers/LCDController.h"
|
||||
|
||||
LCDController* LCDController::_instance = nullptr;
|
||||
|
||||
int LCDController::lcdPutchar(char c, FILE* stream) {
|
||||
if (_instance && _instance->_lcd) {
|
||||
if (c == '\n') {
|
||||
_instance->_cursorRow = (_instance->_cursorRow + 1) % _instance->_lcdRows;
|
||||
_instance->_cursorCol = 0;
|
||||
_instance->_lcd->setCursor(_instance->_cursorCol, _instance->_cursorRow);
|
||||
}
|
||||
else if (c == '\r') {
|
||||
_instance->_cursorCol = 0;
|
||||
_instance->_lcd->setCursor(_instance->_cursorCol, _instance->_cursorRow);
|
||||
}
|
||||
else {
|
||||
_instance->_lcd->write(c);
|
||||
_instance->_cursorCol++;
|
||||
|
||||
if (_instance->_cursorCol >= _instance->_lcdCols) {
|
||||
_instance->_cursorRow = (_instance->_cursorRow + 1) % _instance->_lcdRows;
|
||||
_instance->_cursorCol = 0;
|
||||
_instance->_lcd->setCursor(_instance->_cursorCol, _instance->_cursorRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LCDController::LCDController(uint8_t rs, uint8_t enable, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
|
||||
int cols, int rows) :
|
||||
_lcdOutput(nullptr),
|
||||
_lcdCols(cols),
|
||||
_lcdRows(rows),
|
||||
_cursorRow(0),
|
||||
_cursorCol(0) {
|
||||
|
||||
_lcd = new LiquidCrystal(rs, enable, d4, d5, d6, d7);
|
||||
_instance = this;
|
||||
|
||||
begin();
|
||||
}
|
||||
|
||||
LCDController::~LCDController() {
|
||||
if (_lcdOutput) fclose(_lcdOutput);
|
||||
if (_lcd) delete _lcd;
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
void LCDController::begin() {
|
||||
_lcd->begin(_lcdCols, _lcdRows);
|
||||
_lcd->clear();
|
||||
|
||||
_lcdOutput = fdevopen(lcdPutchar, NULL);
|
||||
}
|
||||
|
||||
FILE* LCDController::stream() {
|
||||
return _lcdOutput;
|
||||
}
|
||||
|
||||
void LCDController::clear() {
|
||||
if (_lcd) {
|
||||
_lcd->clear();
|
||||
_cursorRow = 0;
|
||||
_cursorCol = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LCDController::setCursor(int col, int row) {
|
||||
if (_lcd) {
|
||||
_cursorCol = col;
|
||||
_cursorRow = row;
|
||||
_lcd->setCursor(col, row);
|
||||
}
|
||||
}
|
||||
|
||||
void LCDController::print(const char* text) {
|
||||
if (_lcd) {
|
||||
_lcd->print(text);
|
||||
|
||||
int len = strlen(text);
|
||||
_cursorCol += len;
|
||||
|
||||
while (_cursorCol >= _lcdCols) {
|
||||
_cursorCol -= _lcdCols;
|
||||
_cursorRow = (_cursorRow + 1) % _lcdRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/drivers/LEDController.cpp
Normal file
88
src/drivers/LEDController.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "drivers/LEDController.h"
|
||||
|
||||
#define BLINK_INTERVAL 500
|
||||
|
||||
LEDController::LEDController(int ledPin) :
|
||||
_ledPin(ledPin),
|
||||
_state(false),
|
||||
_isBlinking(false),
|
||||
_previousMillis(0),
|
||||
_blinkInterval(BLINK_INTERVAL),
|
||||
_blinkCount(0) {
|
||||
|
||||
pinMode(_ledPin, OUTPUT);
|
||||
digitalWrite(_ledPin, LOW);
|
||||
}
|
||||
|
||||
LEDController::LEDController(int ledPin, bool state) :
|
||||
_ledPin(ledPin),
|
||||
_state(state),
|
||||
_isBlinking(false),
|
||||
_previousMillis(0),
|
||||
_blinkInterval(BLINK_INTERVAL),
|
||||
_blinkCount(0) {
|
||||
|
||||
pinMode(_ledPin, OUTPUT);
|
||||
|
||||
if (state) digitalWrite(_ledPin, HIGH);
|
||||
else digitalWrite(_ledPin, LOW);
|
||||
}
|
||||
|
||||
void LEDController::turnOn() {
|
||||
_state = true;
|
||||
digitalWrite(_ledPin, HIGH);
|
||||
}
|
||||
|
||||
void LEDController::turnOff() {
|
||||
_state = false;
|
||||
digitalWrite(_ledPin, LOW);
|
||||
}
|
||||
|
||||
void LEDController::toggle() {
|
||||
_state = !_state;
|
||||
digitalWrite(_ledPin, _state);
|
||||
}
|
||||
|
||||
bool LEDController::getState() const {
|
||||
return _state;
|
||||
}
|
||||
|
||||
void LEDController::blink(bool enable) {
|
||||
_isBlinking = enable;
|
||||
if (!enable) {
|
||||
turnOff();
|
||||
}
|
||||
}
|
||||
|
||||
bool LEDController::isBlinkingEnabled() const {
|
||||
return _isBlinking;
|
||||
}
|
||||
|
||||
void LEDController::interval(unsigned long interval) {
|
||||
_blinkInterval = interval;
|
||||
}
|
||||
|
||||
unsigned long LEDController::getBlinkInterval() const {
|
||||
return _blinkInterval;
|
||||
}
|
||||
|
||||
unsigned long LEDController::getBlinkCount() const {
|
||||
return _blinkCount;
|
||||
}
|
||||
|
||||
void LEDController::tick() {
|
||||
if (_isBlinking) {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
if (currentMillis - _previousMillis >= _blinkInterval) {
|
||||
_previousMillis = currentMillis;
|
||||
toggle();
|
||||
if (_state)_blinkCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LEDController::set(bool value) {
|
||||
if (value) turnOn();
|
||||
else turnOff();
|
||||
}
|
||||
71
src/drivers/MotorController.cpp
Normal file
71
src/drivers/MotorController.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "drivers/MotorController.h"
|
||||
|
||||
MotorController::MotorController(int pinIA, int pinIB) :
|
||||
_pinIA(pinIA),
|
||||
_pinIB(pinIB),
|
||||
_currentPower(0) {
|
||||
|
||||
pinMode(_pinIA, OUTPUT);
|
||||
pinMode(_pinIB, OUTPUT);
|
||||
stop();
|
||||
}
|
||||
|
||||
void MotorController::applyPower() {
|
||||
if (_currentPower == 0) {
|
||||
analogWrite(_pinIA, 0);
|
||||
analogWrite(_pinIB, 0);
|
||||
} else if (_currentPower > 0) {
|
||||
int pwmValue = map(abs(_currentPower), 0, 100, 0, 255);
|
||||
analogWrite(_pinIA, pwmValue);
|
||||
analogWrite(_pinIB, 0);
|
||||
} else {
|
||||
int pwmValue = map(abs(_currentPower), 0, 100, 0, 255);
|
||||
analogWrite(_pinIA, 0);
|
||||
analogWrite(_pinIB, pwmValue);
|
||||
}
|
||||
}
|
||||
|
||||
void MotorController::set(int power) {
|
||||
_currentPower = constrain(power, -100, 100);
|
||||
applyPower();
|
||||
}
|
||||
|
||||
void MotorController::stop() {
|
||||
_currentPower = 0;
|
||||
applyPower();
|
||||
}
|
||||
|
||||
void MotorController::maximum() {
|
||||
if (_currentPower >= 0) {
|
||||
_currentPower = 100;
|
||||
} else {
|
||||
_currentPower = -100;
|
||||
}
|
||||
applyPower();
|
||||
}
|
||||
|
||||
void MotorController::inc() {
|
||||
if (_currentPower == 0) {
|
||||
_currentPower = 10;
|
||||
} else {
|
||||
if (_currentPower > 0) {
|
||||
_currentPower = min(100, _currentPower + 10);
|
||||
} else {
|
||||
_currentPower = max(-100, _currentPower - 10);
|
||||
}
|
||||
}
|
||||
applyPower();
|
||||
}
|
||||
|
||||
void MotorController::dec() {
|
||||
if (_currentPower > 0) {
|
||||
_currentPower = max(0, _currentPower - 10);
|
||||
} else if (_currentPower < 0) {
|
||||
_currentPower = min(0, _currentPower + 10);
|
||||
}
|
||||
applyPower();
|
||||
}
|
||||
|
||||
int MotorController::getPower() const {
|
||||
return _currentPower;
|
||||
}
|
||||
0
src/drivers/PassiveBuzzerController.cpp
Normal file
0
src/drivers/PassiveBuzzerController.cpp
Normal file
90
src/drivers/PhotoresistorController.cpp
Normal file
90
src/drivers/PhotoresistorController.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "drivers/PhotoresistorController.h"
|
||||
|
||||
PhotoresistorController::PhotoresistorController(uint8_t pin, int minValue, int maxValue) :
|
||||
_pin(pin),
|
||||
_lastReadTime(0),
|
||||
_minReadInterval(DEFAULT_MIN_READ_INTERVAL),
|
||||
_lastRawValue(0),
|
||||
_lastPercentValue(0),
|
||||
_lastReadSuccess(false),
|
||||
_numSamples(DEFAULT_SAMPLES),
|
||||
_maxValue(maxValue),
|
||||
_minValue(minValue) {
|
||||
}
|
||||
|
||||
void PhotoresistorController::begin() {
|
||||
pinMode(_pin, INPUT);
|
||||
_lastReadSuccess = true;
|
||||
}
|
||||
|
||||
bool PhotoresistorController::read() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
if (currentTime - _lastReadTime >= _minReadInterval) {
|
||||
_lastReadTime = currentTime;
|
||||
|
||||
long sum = 0;
|
||||
for (uint8_t i = 0; i < _numSamples; i++) {
|
||||
sum += analogRead(_pin);
|
||||
if (_numSamples > 1) {
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
|
||||
_lastRawValue = sum / _numSamples;
|
||||
|
||||
long range = _maxValue - _minValue;
|
||||
if (range <= 0) {
|
||||
_lastPercentValue = 50;
|
||||
} else {
|
||||
int constrainedValue = constrain(_lastRawValue, _minValue, _maxValue);
|
||||
_lastPercentValue = map(constrainedValue, _minValue, _maxValue, 0, 100);
|
||||
}
|
||||
|
||||
_lastReadSuccess = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
int PhotoresistorController::getRawValue() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastRawValue;
|
||||
}
|
||||
|
||||
int PhotoresistorController::getPercentValue() {
|
||||
if (millis() - _lastReadTime >= _minReadInterval) read();
|
||||
return _lastPercentValue;
|
||||
}
|
||||
|
||||
void PhotoresistorController::calibrate(int minValue, int maxValue) {
|
||||
if (minValue < maxValue) {
|
||||
_minValue = minValue;
|
||||
_maxValue = maxValue;
|
||||
}
|
||||
}
|
||||
|
||||
void PhotoresistorController::autoCalibrateDark() {
|
||||
read();
|
||||
_minValue = _lastRawValue;
|
||||
}
|
||||
|
||||
void PhotoresistorController::autoCalibrateBright() {
|
||||
read();
|
||||
_maxValue = _lastRawValue;
|
||||
}
|
||||
|
||||
bool PhotoresistorController::isLastReadSuccessful() const {
|
||||
return _lastReadSuccess;
|
||||
}
|
||||
|
||||
void PhotoresistorController::setMinReadInterval(unsigned long interval) {
|
||||
_minReadInterval = interval;
|
||||
}
|
||||
|
||||
void PhotoresistorController::setNumSamples(uint8_t samples) {
|
||||
if (samples > 0) {
|
||||
_numSamples = samples;
|
||||
}
|
||||
}
|
||||
0
src/drivers/RGBLEDController.cpp
Normal file
0
src/drivers/RGBLEDController.cpp
Normal file
121
src/drivers/ThermistorController.cpp
Normal file
121
src/drivers/ThermistorController.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "drivers/ThermistorController.h"
|
||||
#include <math.h>
|
||||
|
||||
ThermistorController::ThermistorController(
|
||||
int thermistorPin,
|
||||
float seriesResistor,
|
||||
float bParameter,
|
||||
float nominalTemp,
|
||||
float minTemp,
|
||||
float maxTemp
|
||||
) :
|
||||
_thermistorPin(thermistorPin),
|
||||
_seriesResistor(seriesResistor),
|
||||
_bParameter(bParameter),
|
||||
_nominalTemp(nominalTemp),
|
||||
_minTemp(minTemp),
|
||||
_maxTemp(maxTemp),
|
||||
_bufferIndex(0),
|
||||
_bufferFilled(false),
|
||||
_filteredRaw(0),
|
||||
_smoothedRaw(0),
|
||||
_resistance(0),
|
||||
_temperatureC(0)
|
||||
{
|
||||
pinMode(_thermistorPin, INPUT);
|
||||
|
||||
for (int i = 0; i < _bufferSize; i++) {
|
||||
_rawReadings[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermistorController::update() {
|
||||
float rawValue = analogRead(_thermistorPin);
|
||||
|
||||
_rawReadings[_bufferIndex] = rawValue;
|
||||
|
||||
_bufferIndex = (_bufferIndex + 1) % _bufferSize;
|
||||
if (_bufferIndex == 0) _bufferFilled = true;
|
||||
|
||||
_filteredRaw = applySaltPepperFilter();
|
||||
_smoothedRaw = applyWeightedMovingAverage();
|
||||
_resistance = calculateResistance(_smoothedRaw);
|
||||
_temperatureC = calculateTemperature(_resistance);
|
||||
_temperatureC = applySaturation(_temperatureC, _minTemp, _maxTemp);
|
||||
}
|
||||
|
||||
int compare(const void* a, const void* b) {
|
||||
return (*(int*)a - *(int*)b);
|
||||
}
|
||||
|
||||
float ThermistorController::applySaltPepperFilter() {
|
||||
if (!_bufferFilled) {
|
||||
return _rawReadings[(_bufferIndex - 1 + _bufferSize) % _bufferSize];
|
||||
}
|
||||
|
||||
float sortedValues[_bufferSize];
|
||||
for (int i = 0; i < _bufferSize; i++) {
|
||||
sortedValues[i] = _rawReadings[i];
|
||||
}
|
||||
|
||||
qsort(sortedValues, _bufferSize, sizeof(int), compare);
|
||||
|
||||
return sortedValues[_bufferSize / 2];
|
||||
}
|
||||
|
||||
float ThermistorController::applyWeightedMovingAverage() {
|
||||
if (!_bufferFilled) {
|
||||
return _filteredRaw;
|
||||
}
|
||||
|
||||
float weightedSum = 0;
|
||||
float sumOfWeights = 0;
|
||||
|
||||
for (int i = 0; i < _bufferSize; i++) {
|
||||
int index = (_bufferIndex - i - 1 + _bufferSize) % _bufferSize;
|
||||
weightedSum += _rawReadings[index] * _weights[i];
|
||||
sumOfWeights += _weights[i];
|
||||
}
|
||||
|
||||
return weightedSum / sumOfWeights;
|
||||
}
|
||||
|
||||
float ThermistorController::calculateResistance(float adcValue) {
|
||||
return (1023.0 * _seriesResistor) / adcValue - _seriesResistor;
|
||||
}
|
||||
|
||||
float ThermistorController::calculateTemperature(float resistance) {
|
||||
float logR = log(resistance / 10000.0);
|
||||
float temp = (_bParameter / (logR + (_bParameter / (273.15 + _nominalTemp)))) - 273.15;
|
||||
return temp;
|
||||
}
|
||||
|
||||
float ThermistorController::applySaturation(float value, float min, float max) {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
}
|
||||
|
||||
float ThermistorController::getRawValue() const {
|
||||
return _rawReadings[(_bufferIndex - 1 + _bufferSize) % _bufferSize];
|
||||
}
|
||||
|
||||
float ThermistorController::getFilteredRaw() const {
|
||||
return _filteredRaw;
|
||||
}
|
||||
|
||||
float ThermistorController::getSmoothedRaw() const {
|
||||
return _smoothedRaw;
|
||||
}
|
||||
|
||||
float ThermistorController::getResistance() const {
|
||||
return _resistance;
|
||||
}
|
||||
|
||||
float ThermistorController::getTemperatureC() const {
|
||||
return _temperatureC;
|
||||
}
|
||||
|
||||
float ThermistorController::getTemperatureF() const {
|
||||
return _temperatureC * 9.0 / 5.0 + 32.0;
|
||||
}
|
||||
45
src/labs/Lab2_1.cpp
Normal file
45
src/labs/Lab2_1.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "labs/Lab2_1.h"
|
||||
|
||||
void TaskOne(bool* state, ButtonController* toggle, LEDController* led) {
|
||||
if (toggle->wasOn()) *state = !*state;
|
||||
led->set(*state);
|
||||
}
|
||||
|
||||
void TaskTwo(bool* toggleState, LEDController* led) {
|
||||
led->tick();
|
||||
led->blink(!*toggleState);
|
||||
}
|
||||
|
||||
void TaskThree(int* delayMs, ButtonController* dec, ButtonController* inc, LEDController* led) {
|
||||
*delayMs = dec->wasOn() ? max(200, *delayMs - 200) : inc->wasOn() ? min(4000, *delayMs + 200) : *delayMs;
|
||||
led->interval(*delayMs);
|
||||
}
|
||||
|
||||
void TaskIdle(int* lastReportTime, bool* toggleState, int* delayState, LCDController* lcd) {
|
||||
if (millis() - *lastReportTime < 300) return;
|
||||
|
||||
*lastReportTime = millis();
|
||||
lcd->clear();
|
||||
printf("Toggle: %s\nDelay: %d ms", *toggleState ? "ON" : "OFF", *delayState);
|
||||
}
|
||||
|
||||
void Lab2_1Task(void* pv) {
|
||||
LEDController ledToggle(LED_PIN), ledBlink(LED_BLINK_PIN);
|
||||
LCDController lcd = LCDController(RS, EN, D4, D5, D6, D7);
|
||||
ButtonController tog(BUTTON_TOGGLE_PIN), dec(BUTTON_DECREMENT_PIN), inc(BUTTON_INCREMENT_PIN);
|
||||
|
||||
stdout = lcd.stream();
|
||||
|
||||
bool toggleState = false;
|
||||
int delayMs = 1000;
|
||||
int lastReportTime = 0;
|
||||
|
||||
while(true) {
|
||||
TaskOne(&toggleState, &tog, &ledToggle);
|
||||
TaskTwo(&toggleState, &ledBlink);
|
||||
TaskThree(&delayMs, &dec, &inc, &ledBlink);
|
||||
TaskIdle(&lastReportTime, &toggleState, &delayMs, &lcd);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
110
src/labs/Lab2_2.cpp
Normal file
110
src/labs/Lab2_2.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "labs/Lab2_2.h"
|
||||
|
||||
void ButtonLedTask(void* parameters) {
|
||||
TaskParameters* params = (TaskParameters*)parameters;
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
|
||||
while(true) {
|
||||
if (params->button->wasOn()) {
|
||||
params->lcd->clear();
|
||||
params->led->set(true);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
xSemaphoreGive(params->buttonSemaphore);
|
||||
params->led->set(false);
|
||||
}
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(10));
|
||||
}
|
||||
}
|
||||
|
||||
void SyncTask(void* parameters) {
|
||||
TaskParameters* params = (TaskParameters*)parameters;
|
||||
int N = 0;
|
||||
|
||||
while(true) {
|
||||
if (xSemaphoreTake(params->buttonSemaphore, portMAX_DELAY) == pdTRUE) {
|
||||
N = N + 1;
|
||||
|
||||
for (int i = 1; i <= N; i++) {
|
||||
xQueueSendToFront(params->dataQueue, &i, portMAX_DELAY);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
// uint8_t endMarker = 0;
|
||||
// xQueueSendToFront(params->dataQueue, &endMarker, portMAX_DELAY);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
params->blinkLed->set(true);
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
params->blinkLed->set(false);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncTask(void* parameters) {
|
||||
TaskParameters* params = (TaskParameters*)parameters;
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
uint8_t receivedByte;
|
||||
|
||||
while(true) {
|
||||
while (xQueueReceive(params->dataQueue, &receivedByte, 0) == pdTRUE) {
|
||||
if (receivedByte == 0) {
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%d", receivedByte);
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
void Lab2_2Task(void* pv) {
|
||||
LEDController ledButton(LED_BUTTON_PIN), ledBlink(LED_BLINK_PIN);
|
||||
LCDController lcd = LCDController(RS, EN, D4, D5, D6, D7);
|
||||
ButtonController button(BUTTON_PIN);
|
||||
|
||||
stdout = lcd.stream();
|
||||
|
||||
SemaphoreHandle_t buttonSemaphore = xSemaphoreCreateBinary();
|
||||
|
||||
QueueHandle_t dataQueue = xQueueCreate(100, sizeof(uint8_t));
|
||||
|
||||
TaskParameters taskParams;
|
||||
taskParams.button = &button;
|
||||
taskParams.led = &ledButton;
|
||||
taskParams.blinkLed = &ledBlink;
|
||||
taskParams.lcd = &lcd;
|
||||
taskParams.buttonSemaphore = buttonSemaphore;
|
||||
taskParams.dataQueue = dataQueue;
|
||||
|
||||
xTaskCreate(
|
||||
ButtonLedTask,
|
||||
"ButtonLed",
|
||||
configMINIMAL_STACK_SIZE,
|
||||
&taskParams,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
xTaskCreate(
|
||||
SyncTask,
|
||||
"Sync",
|
||||
configMINIMAL_STACK_SIZE,
|
||||
&taskParams,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
xTaskCreate(
|
||||
AsyncTask,
|
||||
"Async",
|
||||
configMINIMAL_STACK_SIZE,
|
||||
&taskParams,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
176
src/labs/Lab3_1.cpp
Normal file
176
src/labs/Lab3_1.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "labs/Lab3_1.h"
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
|
||||
void Lab3_1Task(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
stdout = lcd.stream();
|
||||
|
||||
const char* sensors[] = {
|
||||
" DHT ", " Accltr ", " Light ", " Distance "
|
||||
};
|
||||
const int totalSensors = 4;
|
||||
int currentSensor = 0;
|
||||
|
||||
auto printSelection = [&]() {
|
||||
lcd.clear();
|
||||
printf("Picked:\n<-%s->", sensors[currentSensor]);
|
||||
};
|
||||
|
||||
printf("Choose sensor <>");
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
printSelection();
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
JoystickDirection dir = joystick.getDirection();
|
||||
|
||||
if (dir == LEFT || dir == RIGHT) {
|
||||
currentSensor = (dir == LEFT) ? (currentSensor + totalSensors - 1) % totalSensors : (currentSensor + 1) % totalSensors;
|
||||
printSelection();
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
}
|
||||
|
||||
if (joystick.isPressed()) {
|
||||
lcd.clear();
|
||||
switch (currentSensor) {
|
||||
case 0: xTaskCreate(DHTTask, "DHT", 512, NULL, 1, NULL); break;
|
||||
case 1: xTaskCreate(AccelerometerTask, "Accelerometer", 512, NULL, 1, NULL); break;
|
||||
case 2: xTaskCreate(PhotoresistorTask, "Photoresistor", 512, NULL, 1, NULL); break;
|
||||
case 3: xTaskCreate(DistanceTask, "Distance", 512, NULL, 1, NULL); break;
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
|
||||
void DHTTask(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
DHTController dht = DHTController(DHT_PIN);
|
||||
stdout = lcd.stream();
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
|
||||
if(joystick.isPressed()) {
|
||||
xTaskCreate(Lab3_1Task, "Lab3_1", 512, NULL, 1, NULL);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
lcd.clear();
|
||||
bool success = dht.read();
|
||||
|
||||
float temp = dht.getTemperature();
|
||||
float hum = dht.getHumidity();
|
||||
|
||||
if(success && !isnan(temp) && !isnan(hum)) printf("Temp: %d.%d C\nHumi: %d.%d %%", (int)temp, (int)((temp - (int)temp) * 10), (int)hum, (int)((hum - (int)hum) * 10));
|
||||
else printf("Sensor read\nfailed!");
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
|
||||
void AccelerometerTask(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
ADXL345Controller accel;
|
||||
stdout = lcd.stream();
|
||||
|
||||
accel.begin();
|
||||
accel.setRange(3);
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
|
||||
if(joystick.isPressed()) {
|
||||
xTaskCreate(Lab3_1Task, "Lab3_1", 512, NULL, 1, NULL);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
lcd.clear();
|
||||
bool success = accel.read();
|
||||
|
||||
double x = accel.getX();
|
||||
double y = accel.getY();
|
||||
double z = accel.getZ();
|
||||
|
||||
if(success) {
|
||||
int x_whole = (int)x;
|
||||
int x_dec = abs((int)((x - x_whole) * 100));
|
||||
|
||||
int y_whole = (int)y;
|
||||
int y_dec = abs((int)((y - y_whole) * 100));
|
||||
|
||||
int z_whole = (int)z;
|
||||
int z_dec = abs((int)((z - z_whole) * 100));
|
||||
|
||||
printf("Accelr XYZ:\n%d.%02d %d.%02d %d.%02d", x_whole, x_dec, y_whole, y_dec, z_whole, z_dec);
|
||||
} else printf("Accel read\nfailed!");
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
|
||||
void PhotoresistorTask(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
PhotoresistorController photoresistor(PHOTORESISTOR_PIN);
|
||||
stdout = lcd.stream();
|
||||
|
||||
photoresistor.begin();
|
||||
photoresistor.setNumSamples(5);
|
||||
photoresistor.calibrate(100, 900);
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
|
||||
if(joystick.isPressed()) {
|
||||
xTaskCreate(Lab3_1Task, "Lab3_1", 512, NULL, 1, NULL);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
lcd.clear();
|
||||
bool success = photoresistor.read();
|
||||
|
||||
int rawValue = photoresistor.getRawValue();
|
||||
int percentValue = photoresistor.getPercentValue();
|
||||
|
||||
if(success) printf("Light Level:\nVal:%4d (%3d%%)", rawValue, percentValue);
|
||||
else printf("Sensor read\nfailed!");
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
|
||||
void DistanceTask(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
DistanceSensorController distance(TRIG_PIN, ECHO_PIN);
|
||||
stdout = lcd.stream();
|
||||
|
||||
distance.begin();
|
||||
|
||||
distance.setNumSamples(3);
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
|
||||
if(joystick.isPressed()) {
|
||||
xTaskCreate(Lab3_1Task, "Lab3_1", 512, NULL, 1, NULL);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
lcd.clear();
|
||||
bool success = distance.read();
|
||||
|
||||
long distanceCm = distance.getDistanceCm();
|
||||
|
||||
if(success) printf("Distance:\n%ld cm", distanceCm);
|
||||
else printf("Sensor read\nfailed!");
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
}
|
||||
36
src/labs/Lab3_2.cpp
Normal file
36
src/labs/Lab3_2.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "labs/Lab3_2.h"
|
||||
|
||||
void Lab3_2Task(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
|
||||
ThermistorController thermistor(THERMISTOR_PIN, 10000.0, 3435.0, 25.0, -55.0, 125.0);
|
||||
|
||||
stdout = lcd.stream();
|
||||
|
||||
const TickType_t xFrequency = pdMS_TO_TICKS(200);
|
||||
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||
|
||||
while (true) {
|
||||
thermistor.update();
|
||||
|
||||
float tempC = thermistor.getTemperatureC();
|
||||
float tempF = thermistor.getTemperatureF();
|
||||
float resistance = thermistor.getResistance();
|
||||
|
||||
int tempCInt = (int)tempC;
|
||||
int tempCDec = (int)((tempC - tempCInt) * 10);
|
||||
|
||||
int tempFInt = (int)tempF;
|
||||
int tempFDec = (int)((tempF - tempFInt) * 10);
|
||||
|
||||
int resInt = (int)(resistance / 1000);
|
||||
int resDec = (int)((resistance / 1000.0 - resInt) * 10);
|
||||
|
||||
lcd.clear();
|
||||
printf("Temp: %d.%d C", tempCInt, tempCDec);
|
||||
lcd.setCursor(0, 1);
|
||||
printf("%d.%d F %d.%dk", tempFInt, tempFDec, resInt, resDec);
|
||||
|
||||
vTaskDelayUntil(&xLastWakeTime, xFrequency);
|
||||
}
|
||||
}
|
||||
47
src/labs/Lab4_1.cpp
Normal file
47
src/labs/Lab4_1.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "labs/Lab4_1.h"
|
||||
#include <Arduino_FreeRTOS.h>
|
||||
|
||||
void Lab4_1Task(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
RelayController relay(RELAY_PIN);
|
||||
stdout = lcd.stream();
|
||||
|
||||
const char* commands[] = {
|
||||
"Turn ON", "Turn OFF"
|
||||
};
|
||||
|
||||
const int totalCommands = 2;
|
||||
int currentCommand = 0;
|
||||
|
||||
auto printSelection = [&]() {
|
||||
lcd.clear();
|
||||
printf("Relay is %s\n%s ->", relay.isConnected() ? "ON" : "OFF", commands[currentCommand]);
|
||||
};
|
||||
|
||||
printf("Pick command <>");
|
||||
while(joystick.isCentered()) joystick.tick();
|
||||
printSelection();
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
JoystickDirection dir = joystick.getDirection();
|
||||
|
||||
if (dir == LEFT || dir == RIGHT) {
|
||||
currentCommand = (dir == LEFT) ? (currentCommand + totalCommands - 1) % totalCommands : (currentCommand + 1) % totalCommands;
|
||||
printSelection();
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
}
|
||||
|
||||
if (joystick.isPressed()) {
|
||||
lcd.clear();
|
||||
switch (currentCommand) {
|
||||
case 0: relay.connect(); break;
|
||||
case 1: relay.disconnect(); break;
|
||||
}
|
||||
printSelection();
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
74
src/labs/Lab4_2.cpp
Normal file
74
src/labs/Lab4_2.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "labs/Lab4_2.h"
|
||||
|
||||
void Lab4_2Task(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
MotorController motor(MOTOR_PIN_IA, MOTOR_PIN_IB);
|
||||
RelayController relay(RELAY_PIN);
|
||||
relay.connect();
|
||||
|
||||
stdout = lcd.stream();
|
||||
|
||||
const char* commands[] = {
|
||||
" set ", " stop ", " max ", " inc ", " dec "
|
||||
};
|
||||
|
||||
const int totalCommands = 5;
|
||||
int currentCommand = 0;
|
||||
|
||||
auto printSelection = [&]() {
|
||||
lcd.clear();
|
||||
printf("Power: %d%% \n%s ->", motor.getPower(), commands[currentCommand]);
|
||||
};
|
||||
|
||||
printf("Motor Control\nUse joystick");
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
printSelection();
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
JoystickDirection dir = joystick.getDirection();
|
||||
|
||||
if (dir == LEFT || dir == RIGHT) {
|
||||
currentCommand = (dir == LEFT) ?
|
||||
(currentCommand + totalCommands - 1) % totalCommands :
|
||||
(currentCommand + 1) % totalCommands;
|
||||
printSelection();
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
}
|
||||
|
||||
if (currentCommand == 0 && (dir == UP || dir == DOWN)) {
|
||||
int power = motor.getPower();
|
||||
power = (dir == UP) ? min(100, power + 1) : max(-100, power - 1);
|
||||
motor.set(power);
|
||||
printSelection();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
if (joystick.isPressed()) {
|
||||
lcd.clear();
|
||||
switch (currentCommand) {
|
||||
case 1:
|
||||
motor.stop();
|
||||
printf("Motor stopped");
|
||||
break;
|
||||
case 2:
|
||||
motor.maximum();
|
||||
printf("Max power: %d%%", motor.getPower());
|
||||
break;
|
||||
case 3:
|
||||
motor.inc();
|
||||
printf("Power inc: %d%%", motor.getPower());
|
||||
break;
|
||||
case 4:
|
||||
motor.dec();
|
||||
printf("Power dec: %d%%", motor.getPower());
|
||||
break;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
printSelection();
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
}
|
||||
49
src/labs/LabSelector.cpp
Normal file
49
src/labs/LabSelector.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "labs/LabSelector.h"
|
||||
|
||||
void LabSelectorTask(void* pv) {
|
||||
LCDController lcd(RS, EN, D4, D5, D6, D7);
|
||||
JoystickController joystick(VRX, VRY, SW);
|
||||
stdout = lcd.stream();
|
||||
|
||||
const char* labNames[] = {
|
||||
"Lab2.1", "Lab2.2", "Lab3.1",
|
||||
"Lab3.2", "Lab4.1", "Lab4.2"
|
||||
};
|
||||
const int totalLabs = 6;
|
||||
int currentLab = 0;
|
||||
|
||||
auto printSelection = [&]() {
|
||||
lcd.clear();
|
||||
printf("Selected:\n<- %s ->", labNames[currentLab]);
|
||||
};
|
||||
|
||||
printf("Lab Picker\nUse joystick <>");
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
printSelection();
|
||||
|
||||
while (true) {
|
||||
joystick.tick();
|
||||
JoystickDirection dir = joystick.getDirection();
|
||||
|
||||
if (dir == LEFT || dir == RIGHT) {
|
||||
currentLab = (dir == LEFT) ? (currentLab + totalLabs - 1) % totalLabs : (currentLab + 1) % totalLabs;
|
||||
printSelection();
|
||||
vTaskDelay(pdMS_TO_TICKS(300));
|
||||
}
|
||||
|
||||
if (joystick.isPressed()) {
|
||||
lcd.clear();
|
||||
switch (currentLab) {
|
||||
case 0: xTaskCreate(Lab2_1Task, "Lab2_1", 512, NULL, 1, NULL); break;
|
||||
case 1: xTaskCreate(Lab2_2Task, "Lab2_2", 512, NULL, 1, NULL); break;
|
||||
case 2: xTaskCreate(Lab3_1Task, "Lab3_1", 512, NULL, 1, NULL); break;
|
||||
case 3: xTaskCreate(Lab3_2Task, "Lab3_2", 512, NULL, 1, NULL); break;
|
||||
case 4: xTaskCreate(Lab4_1Task, "Lab4_1", 512, NULL, 1, NULL); break;
|
||||
case 5: xTaskCreate(Lab4_2Task, "Lab4_2", 512, NULL, 1, NULL); break;
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
14
src/main.cpp
Normal file
14
src/main.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "labs/LabSelector.h"
|
||||
|
||||
void setup() {
|
||||
xTaskCreate(
|
||||
LabSelectorTask,
|
||||
"LabPicker",
|
||||
512,
|
||||
NULL,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
11
test/README
Normal file
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
Reference in New Issue
Block a user