first commit

This commit is contained in:
lumijiez
2025-04-28 18:30:29 +03:00
commit a4b88564a4
45 changed files with 2188 additions and 0 deletions

5
.gitignore vendored Normal file
View 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
View 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
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"new": "cpp"
}
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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

View 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();
}
}

View 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;
}

View 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;
}

View 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;
}

View 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);
}

View 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;
}
}
}

View 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();
}

View 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;
}

View File

View 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;
}
}

View File

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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