diff --git a/headcrab-cubemx/Core/Inc/hx711.h b/headcrab-cubemx/Core/Inc/hx711.h new file mode 100644 index 0000000..08f7f25 --- /dev/null +++ b/headcrab-cubemx/Core/Inc/hx711.h @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * @file : hx711.h + * @brief : HX711 library header file + ****************************************************************************** + * @attention + * + *

by leonek + * have fun

+ * + * gnu gpl v3.0 licence forever!~ + * + ****************************************************************************** + */ + +#ifndef HX711_H //we want to include library only once +#define HX711_H + +#include +#include + +// all hxes +typedef enum +{ + HX_A = 0, //top right + HX_B = 1, //top left + HX_C = 2, //bottom left + HX_D = 3 //bottom right +} HX_nr; + +void HX_begin(HX_nr module); +uint32_t HX_read(HX_nr module); +bool HX_check(HX_nr module); + +#endif \ No newline at end of file diff --git a/headcrab-cubemx/Core/Inc/pca9685.h b/headcrab-cubemx/Core/Inc/pca9685.h new file mode 100644 index 0000000..61b6284 --- /dev/null +++ b/headcrab-cubemx/Core/Inc/pca9685.h @@ -0,0 +1,36 @@ +/** + ****************************************************************************** + * @file : pca9685.h + * @brief : PCA9685 PWM library header file + ****************************************************************************** + * @attention + * + *

by leonek + * have fun

+ * + * gnu gpl v3.0 licence forever!~ + * + ****************************************************************************** + */ + +#ifndef PCA9685_H //we want to include library only once +#define PCA9685_H + +#include +#include + +uint8_t PCA_read8(uint8_t reg); +void PCA_write8(uint8_t reg, uint8_t val); +void PCA_reset(); +void PCA_setBit(uint8_t reg, uint8_t bit, bool val); +void PCA_sleepMode(bool s); +void PCA_restartMode(bool s); +void PCA_autoIncrement(bool s); +void PCA_setFreq(int f); +void PCA_setPWM(uint8_t channel, int ontime, int offtime); +void PCA_setPin(uint8_t channel, int value); +long map(long x, long in_min, long in_max, long out_min, long out_max); +void PCA_setServoAngle(uint8_t channel, float angle); +void PCA_begin(); + +#endif \ No newline at end of file diff --git a/headcrab-cubemx/Core/Src/hx711.c b/headcrab-cubemx/Core/Src/hx711.c new file mode 100644 index 0000000..418fec3 --- /dev/null +++ b/headcrab-cubemx/Core/Src/hx711.c @@ -0,0 +1,81 @@ +/** + ****************************************************************************** + * @file : xh711.c + * @brief : XH711 library source file + ****************************************************************************** + * @attention + * + *

by leonek + * have fun

+ * + * gnu gpl v3.0 licence forever!~ + * + ****************************************************************************** + */ +#include +#include +#include +#include +#include +#include "hx711.h" +#include "gpio.h" +#include "main.h" + +typedef struct +{ + GPIO_TypeDef* clk_port; + uint16_t clk_pin; + GPIO_TypeDef* data_port; + uint16_t data_pin; +} HX_ADC; + +static const HX_ADC HXes[] = +{ + {HX0_CLOCK_GPIO_Port, HX0_CLOCK_Pin, HX0_DATA_GPIO_Port, HX0_DATA_Pin}, + {HX1_CLOCK_GPIO_Port, HX1_CLOCK_Pin, HX1_DATA_GPIO_Port, HX1_DATA_Pin}, + {HX2_CLOCK_GPIO_Port, HX2_CLOCK_Pin, HX2_DATA_GPIO_Port, HX2_DATA_Pin}, + {HX3_CLOCK_GPIO_Port, HX3_CLOCK_Pin, HX3_DATA_GPIO_Port, HX3_DATA_Pin} +}; + +#define BITS_A_128 25 +#define BITS_B_32 26 +#define BITS_A_64 27 + +#define CLOCK_BITS BITS_A_128 + +void HX_begin(HX_nr module) +{ + while(HAL_GPIO_ReadPin(HXes[module].data_port, HXes[module].data_pin)); //wait til ready + for(int x = 0; x < CLOCK_BITS; x++) + { + HAL_GPIO_WritePin(HXes[module].data_port, HXes[module].data_pin, GPIO_PIN_SET); + HAL_Delay(1); + HAL_GPIO_WritePin(HXes[module].data_port, HXes[module].data_pin, GPIO_PIN_SET); + HAL_Delay(0); + } +} + +//read +uint32_t HX_read(HX_nr module) +{ + uint32_t result = 0; + while(HAL_GPIO_ReadPin(HXes[module].data_port, HXes[module].data_pin)); //wait til ready + + for(int x = 0; x < CLOCK_BITS; x++) + { + HAL_GPIO_WritePin(HXes[module].data_port, HXes[module].data_pin, GPIO_PIN_SET); + if(x < 25) result |= HAL_GPIO_ReadPin(HXes[module].data_port, HXes[module].data_pin) << x; + HAL_GPIO_WritePin(HXes[module].data_port, HXes[module].data_pin, GPIO_PIN_RESET); + } + return result; +} + +//check the state +bool HX_check(HX_nr module) +{ + if(HAL_GPIO_ReadPin(HXes[module].data_port, HXes[module].data_pin) == GPIO_PIN_SET) + return true; + else + return false; +} + diff --git a/headcrab-cubemx/Core/Src/main.c b/headcrab-cubemx/Core/Src/main.c index e037d5f..c51f03e 100644 --- a/headcrab-cubemx/Core/Src/main.c +++ b/headcrab-cubemx/Core/Src/main.c @@ -35,6 +35,8 @@ #include #include "dfplayermini.h" #include +#include "pca9685.h" +#include "hx711.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -59,62 +61,6 @@ typedef struct #define CRLF 1 #define NOCRLF 0 -#define PCA9685_ADDRESS 0x80 -//registers -#define PCA9685_MODE1 0x00 -#define PCA9685_MODE2 0x01 -#define PCA9685_SUBADR1 0x02 -#define PCA9685_SUBADR2 0x03 -#define PCA9685_SUBADR3 0x04 -#define PCA9685_ALLCALLADR 0x05 -#define PCA9685_LED0_ON_L 0x06 -#define PCA9685_LED0_ON_H 0x07 -#define PCA9685_LED0_OFF_L 0x08 -#define PCA9685_LED0_OFF_H 0x09 -// etc all 16: LED15_OFF_H 0x45 - -#define PCA9685_ALLLED_ON_L 0xFA -#define PCA9685_ALLLED_ON_H 0xFB -#define PCA9685_ALLLED_OFF_L 0xFC -#define PCA9685_ALLLED_OFF_H 0xFD -#define PCA9685_PRESCALE 0xFE - -// MODE1 bits -#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */ -#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */ -#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */ -#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */ -#define PCA9685_BIT_SLEEP 0x04 /**< Low power mode. Oscillator off */ -#define PCA9685_BIT_AI 0x05 /**< Auto-Increment enabled */ -#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */ -#define PCA9685_BIT_RESTART 0x07 /**< Restart enabled */ -// MODE2 bits -#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */ -#define MODE2_OUTNE_1 0x02 /**< Active LOW output enable input - high impedience */ -#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */ -#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */ -#define MODE2_INVRT 0x10 /**< Output logic state inverted */ - -const int servoMinMaxValues[16][2] = -{ - {140, 410}, - {100, 480}, - {80, 470}, - {0, 0}, - {150, 440}, - {100, 480}, - {80, 470}, - {0, 0}, - {150, 450}, - {110, 480}, - {160, 510}, //fix - {0, 0}, - {170, 470}, - {100, 470}, - {150, 520}, - {0, 0} -}; - /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -148,120 +94,6 @@ bool debug_echo = false; void SystemClock_Config(void); /* USER CODE BEGIN PFP */ -uint8_t PCA_read8(uint8_t reg) -{ - uint8_t value = 0; - HAL_I2C_Mem_Read(&hi2c1, PCA9685_ADDRESS, reg, 1, &value, 1, HAL_MAX_DELAY); - return value; -} - -void PCA_write8(uint8_t reg, uint8_t val) -{ - HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, reg, 1, &val, 1, HAL_MAX_DELAY); -} - -void PCA_reset() -{ - uint8_t rst = 0x06; - HAL_I2C_Master_Transmit(&hi2c1, 0x00, &rst, 1, HAL_MAX_DELAY); - HAL_Delay(10); -} - -//register, bit place, the bit (lol) -void PCA_setBit(uint8_t reg, uint8_t bit, bool val) -{ - uint8_t value = PCA_read8(reg); - - if(val) value |= val << bit; - else value &= ~(!val << bit); - - char b[10]; - itoa(value, b, 16); - char msg[32] = "VALUE: "; - strcat(msg, b); - debug_serialWrite(msg, CRLF); - - PCA_write8(reg, value); -} - -void PCA_sleepMode(bool s) -{ - PCA_setBit(PCA9685_MODE1, PCA9685_BIT_SLEEP, s); -} - -void PCA_restartMode(bool s) -{ - PCA_setBit(PCA9685_MODE1, PCA9685_BIT_RESTART, s); -} -void PCA_autoIncrement(bool s) -{ - PCA_setBit(PCA9685_MODE1, PCA9685_BIT_AI, s); -} - -void PCA_setFreq(int f) -{ - uint8_t prescale = 0; - if(f >= 1526) - prescale = 0x03; - else if(f <= 24) - prescale = 0xFF; - else - { - float val = (25000000 / (4096 * (float)f)) - 1; - prescale = round(val); - } - - PCA_sleepMode(1); - PCA_write8(PCA9685_PRESCALE, prescale); - PCA_sleepMode(0); - PCA_restartMode(1); -} - -void PCA_setPWM(uint8_t channel, int ontime, int offtime) -{ - uint8_t reg; - uint8_t buffer[4]; - - reg = PCA9685_LED0_ON_L + (4 * channel); - buffer[0] = ontime; - buffer[1] = ontime >> 8; - buffer[2] = offtime; - buffer[3] = offtime >> 8; - - HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, reg, 1, buffer, 4, HAL_MAX_DELAY); -} - -void PCA_setPin(uint8_t channel, int value) -{ - if(value == 4095) - PCA_setPWM(channel, 4096, 0); - else if(value == 0) - PCA_setPWM(channel, 0, 4096); - else - PCA_setPWM(channel, 0, value); -} - -//straight from arduino ide :3 -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -void PCA_setServoAngle(uint8_t channel, float angle) -{ - int a; - if(angle < 0) a = 0; - else a = map((uint16_t)angle, 0, 180, servoMinMaxValues[channel][0], servoMinMaxValues[channel][1]); - PCA_setPin(channel, a); -} - -void PCA_begin() -{ - PCA_reset(); - PCA_setFreq(50); - PCA_autoIncrement(true); -} - //turn on/off builtin leds void led_set(int led, bool turn_on) { @@ -271,6 +103,7 @@ void led_set(int led, bool turn_on) HAL_GPIO_WritePin(LEDs[led].port, LEDs[led].pin, state); } +// toggle yay void led_toggle(int led) { if (led >= 0 && led < 8) @@ -319,8 +152,6 @@ HAL_StatusTypeDef debug_serialWrite(char* message, bool nl) return HAL_UART_Transmit(&huart1, (uint8_t*)&msg, strlen(msg), HAL_MAX_DELAY); } - - // split received data and execute a command void debug_executeSerial() { @@ -444,6 +275,7 @@ void debug_handleSerial() } } +// interrupt on receive void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &huart1) @@ -516,6 +348,10 @@ int main(void) PCA_begin(); + HX_begin(0); + + + /* USER CODE END 2 */ /* Infinite loop */ @@ -523,6 +359,11 @@ int main(void) while (1) { led_toggle(6); + char msg[32] = "ODCZYT: "; + char buff[32]; + itoa(HX_read(0), buff, 2); + strcat(msg, buff); + debug_serialWrite(msg, 1); HAL_Delay(100); HAL_IWDG_Refresh(&hiwdg); /* USER CODE END WHILE */ diff --git a/headcrab-cubemx/Core/Src/pca9685.c b/headcrab-cubemx/Core/Src/pca9685.c new file mode 100644 index 0000000..f0e8576 --- /dev/null +++ b/headcrab-cubemx/Core/Src/pca9685.c @@ -0,0 +1,191 @@ +/** + ****************************************************************************** + * @file : pca9685.c + * @brief : PCA9685 library source file + ****************************************************************************** + * @attention + * + *

by leonek + * have fun

+ * + * gnu gpl v3.0 licence forever!~ + * + ****************************************************************************** + */ +#include +#include +#include +#include +#include +#include "pca9685.h" +#include "i2c.h" + +#define PCA9685_ADDRESS 0x80 +//registers +#define PCA9685_MODE1 0x00 +#define PCA9685_MODE2 0x01 +#define PCA9685_SUBADR1 0x02 +#define PCA9685_SUBADR2 0x03 +#define PCA9685_SUBADR3 0x04 +#define PCA9685_ALLCALLADR 0x05 +#define PCA9685_LED0_ON_L 0x06 +#define PCA9685_LED0_ON_H 0x07 +#define PCA9685_LED0_OFF_L 0x08 +#define PCA9685_LED0_OFF_H 0x09 +// etc all 16: LED15_OFF_H 0x45 + +#define PCA9685_ALLLED_ON_L 0xFA +#define PCA9685_ALLLED_ON_H 0xFB +#define PCA9685_ALLLED_OFF_L 0xFC +#define PCA9685_ALLLED_OFF_H 0xFD +#define PCA9685_PRESCALE 0xFE + +// MODE1 bits +#define MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */ +#define MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */ +#define MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */ +#define MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */ +#define PCA9685_BIT_SLEEP 0x04 /**< Low power mode. Oscillator off */ +#define PCA9685_BIT_AI 0x05 /**< Auto-Increment enabled */ +#define MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */ +#define PCA9685_BIT_RESTART 0x07 /**< Restart enabled */ +// MODE2 bits +#define MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */ +#define MODE2_OUTNE_1 0x02 /**< Active LOW output enable input - high impedience */ +#define MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */ +#define MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */ +#define MODE2_INVRT 0x10 /**< Output logic state inverted */ + +const int servoMinMaxValues[16][2] = +{ + {140, 410}, + {100, 480}, + {80, 470}, + {0, 0}, + {150, 440}, + {100, 480}, + {80, 470}, + {0, 0}, + {150, 450}, + {110, 480}, + {160, 510}, //fix + {0, 0}, + {170, 470}, + {100, 470}, + {150, 520}, + {0, 0} +}; + +uint8_t PCA_read8(uint8_t reg) +{ + uint8_t value = 0; + HAL_I2C_Mem_Read(&hi2c1, PCA9685_ADDRESS, reg, 1, &value, 1, HAL_MAX_DELAY); + return value; +} + +void PCA_write8(uint8_t reg, uint8_t val) +{ + HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, reg, 1, &val, 1, HAL_MAX_DELAY); +} + +void PCA_reset() +{ + uint8_t rst = 0x06; + HAL_I2C_Master_Transmit(&hi2c1, 0x00, &rst, 1, HAL_MAX_DELAY); + HAL_Delay(10); +} + +//register, bit place, the bit (lol) +void PCA_setBit(uint8_t reg, uint8_t bit, bool val) +{ + uint8_t value = PCA_read8(reg); + + if(val) value |= val << bit; + else value &= ~(!val << bit); + + char b[10]; + itoa(value, b, 16); + char msg[32] = "VALUE: "; + strcat(msg, b); + debug_serialWrite(msg, 1); + + PCA_write8(reg, value); +} + +void PCA_sleepMode(bool s) +{ + PCA_setBit(PCA9685_MODE1, PCA9685_BIT_SLEEP, s); +} + +void PCA_restartMode(bool s) +{ + PCA_setBit(PCA9685_MODE1, PCA9685_BIT_RESTART, s); +} +void PCA_autoIncrement(bool s) +{ + PCA_setBit(PCA9685_MODE1, PCA9685_BIT_AI, s); +} + +void PCA_setFreq(int f) +{ + uint8_t prescale = 0; + if(f >= 1526) + prescale = 0x03; + else if(f <= 24) + prescale = 0xFF; + else + { + float val = (25000000 / (4096 * (float)f)) - 1; + prescale = round(val); + } + + PCA_sleepMode(1); + PCA_write8(PCA9685_PRESCALE, prescale); + PCA_sleepMode(0); + PCA_restartMode(1); +} + +void PCA_setPWM(uint8_t channel, int ontime, int offtime) +{ + uint8_t reg; + uint8_t buffer[4]; + + reg = PCA9685_LED0_ON_L + (4 * channel); + buffer[0] = ontime; + buffer[1] = ontime >> 8; + buffer[2] = offtime; + buffer[3] = offtime >> 8; + + HAL_I2C_Mem_Write(&hi2c1, PCA9685_ADDRESS, reg, 1, buffer, 4, HAL_MAX_DELAY); +} + +void PCA_setPin(uint8_t channel, int value) +{ + if(value == 4095) + PCA_setPWM(channel, 4096, 0); + else if(value == 0) + PCA_setPWM(channel, 0, 4096); + else + PCA_setPWM(channel, 0, value); +} + +//straight from arduino ide :3 +long map(long x, long in_min, long in_max, long out_min, long out_max) +{ + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +void PCA_setServoAngle(uint8_t channel, float angle) +{ + int a; + if(angle < 0) a = 0; + else a = map((uint16_t)angle, 0, 180, servoMinMaxValues[channel][0], servoMinMaxValues[channel][1]); + PCA_setPin(channel, a); +} + +void PCA_begin() +{ + PCA_reset(); + PCA_setFreq(50); + PCA_autoIncrement(true); +} \ No newline at end of file diff --git a/headcrab-disco/platformio_cubemx.code-workspace b/headcrab-disco/platformio_cubemx.code-workspace index 1b0246f..0ff59e5 100644 --- a/headcrab-disco/platformio_cubemx.code-workspace +++ b/headcrab-disco/platformio_cubemx.code-workspace @@ -23,7 +23,8 @@ "sstream": "c", "main.h": "c", "unordered_map": "cpp", - "initializer_list": "cpp" + "initializer_list": "cpp", + "stdlib.h": "c" } } } \ No newline at end of file