pid seems to work now

master
Jens Noack 2023-03-24 21:51:39 +01:00
parent c390c741d2
commit 57580f4436
4 changed files with 68 additions and 130 deletions

View File

@ -19,7 +19,7 @@
#include "capportal.hpp"
#include <esp32-hal-timer.h>
//#define HAS_MQTT
#define HAS_MQTT
#ifdef HAS_MQTT
#include "mqtt.hpp"
#include "json.hpp"
@ -56,13 +56,13 @@ Oled display;
const unsigned long MAX_TIME_PER_TURN_MS = 600;
const unsigned long UPDATE_TURN_VALUES_EVERY_MS = 1000;
const unsigned long UPDATE_ESC_EVERY_MS = 500;
const unsigned long UPDATE_ESC_EVERY_MS = 200;
const uint8_t HALL_SENSORS_COUNT = 8; // input, sec, min, hour, day, week, month, year
const uint8_t ALL_DATA_COUNT = HALL_SENSORS_COUNT;
const uint8_t HALL_TICKS_PER_TURN = 4;
const uint8_t HALL_NR_TURN = 4;
const uint8_t HALL_NR_TURN = 2;
const uint8_t HALL_MIN_PULSE_MS = 50;
volatile DataStruct AllData[ALL_DATA_COUNT];
@ -89,10 +89,8 @@ const char ** Hall_units = Data_units;
const float * Hall_units_factor = Data_units_factor;
const uint8_t LED_BUILTIN = 2;
const uint8_t POTI_PIN = 36; // never use ADC2 (GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27) if Wifi is active ... use ADC1 instead (GPIO32-GPIO39)
const uint8_t ESC_PIN = 16;
const uint8_t HALL1_PIN = 34;
const uint8_t HALL2_PIN = 35;
const uint8_t HALL3_PIN = 32;
@ -102,13 +100,11 @@ const uint8_t HALL6_PIN = 26;
const uint8_t HALL7_PIN = 27;
const uint8_t HALL8_PIN = 14;
const uint8_t TIME_PER_ROUND_VALS = 10;
const uint8_t TIME_PER_ROUND_VALS = 20;
const uint16_t MIN_SPEED = 500;
const uint16_t MAX_SPEED = 5000;
const uint8_t MAX_ESC_SPEED = 180;
const uint8_t MIN_ESC_SPEED = 0;
const uint16_t MAX_POTI_VALUE = 4095;
const uint16_t JITTER_POTI_PERCENT = 10;
const uint8_t MIN_ESC_SPEED = 7;
#endif //MAIN_HPP

View File

@ -10,11 +10,11 @@ class Oled
{
private:
const unsigned long PAGE_VIEW_TIME_MS = 10000;
const uint8_t HALLS_PER_PAGE = 4;
const uint8_t MAX_PAGE_NR = HALL2;
const uint8_t HALLS_PER_PAGE = 2;
const uint8_t MAX_PAGE_NR = HALL4;
const uint8_t MIN_PAGE_NR = SPEED;
enum pages {SPEED, HALL1, HALL2};
enum pages {SPEED, HALL1, HALL2, HALL3, HALL4};
//SSD1306Wire display(0x3c, SDA, SCL);
SSD1306Wire *display;
@ -26,7 +26,7 @@ class Oled
uint8_t page_nr = MIN_PAGE_NR;
void next_page(bool speedchange);
void show_page_header( String ipaddr, pages page);
void show_page_header( String ipaddr);
void show_speed(int speed, int min_speed, int max_speed, double u_min, unsigned long runtime, pages page);
void show_halls(volatile DataStruct *HallData, uint8_t hall_sensor_count, pages page);
void show_page_footer(pages page);

View File

@ -1,8 +1,5 @@
#include "main.hpp"
int Drehregler; // Ausgabewert des Drehreglers
int speed; // Das Wort "Geschwindigkeit" steht als Variable für den Ansteuerungswert am ESC.
int last_speed;
volatile uint8_t time_per_round_pointer = 0;
volatile double time_per_round_ms[TIME_PER_ROUND_VALS];
@ -14,15 +11,14 @@ double integ = 0.0;
double derivative = 0.0;
double esc_output = 0.0;
int ser_esc_output = -1;
double ser_speed = 1000;
double speed = 1000.0;
double last_error = 0.0;
int esc_value = 0;
double goal_speed = 0;
double current_speed = 0;
double err = 0;
double output = 0.0;
double kp = 0.03;
double ki = 0.01;
double ki = 0.008;
double kd = 0.002;
@ -42,7 +38,6 @@ void data_generate();
void data_store();
void data_check();
void data_init();
void speed_get();
void speed_set();
void PID();
@ -117,20 +112,15 @@ void setup()
attachInterrupt(digitalPinToInterrupt(HALL8_PIN), ISR_HALL8, FALLING);
#endif
Serial.println(" Auf gehts ... ");
ESC.write(50);
delay(2000);
}
void loop()
{
capportal.handle();
get_serial_cmd();
data_generate();
count_secs(&run_time);
speed_get();
speed_set();
data_check();
data_store();
@ -170,7 +160,7 @@ void PID()
derivative = 0;
}
err = goal_speed - current_speed;
err = constrain(speed - current_speed, -100, 100);
double int_integ = integ + err;
double int_derivative = err - last_error;
if(ki != 0)
@ -265,16 +255,18 @@ unsigned long time_per_round_calc()
{
for (uint8_t i= 0; i < TIME_PER_ROUND_VALS; i++)
{
time_per_round_ms[i] = TIME_PER_ROUND_VALS;
time_per_round_ms[i] = HALL_NR_TURN*MAX_TIME_PER_TURN_MS;
}
mid_time = MAX_TIME_PER_TURN_MS;
}
/*
static unsigned long last_mid_time = millis();
if(millis() - last_mid_time > 500)
{
Serial.printf(">turn_time_ms:%d\n>real_values:%d\n", mid_time, real_values);
last_mid_time = millis();
}
*/
return(mid_time);
}
@ -284,65 +276,12 @@ void speed_set()
if(0 == last_esc_write_ms || millis() - last_esc_write_ms > UPDATE_ESC_EVERY_MS)
{
PID();
//Serial.printf(">periodticks0:%d\n>ticks0turntime_ms:%d\n>goal:%06.3f\n>current:%06.3f\n>err:%06.3f\n>integ:%06.3f\n>derive:%06.3f\n>output:%06.3f\n>esc_output:%06.3f\n",
// HallData[0].period_ticks, time_per_round_ms[time_per_round_pointer], goal_speed, current_speed, err, integ, derivative, output, esc_output);
Serial.printf(">period_ticks:%d\n>time_per_round_last_updated_ms:%d\n>goal_speed:%06.3f\n>current:%06.3f\n>err:%06.3f\n",
HallData[0].period_ticks,HallData[0].act_update_ms, goal_speed, current_speed, err);
Serial.printf(">speed:%06.3f\n>current:%06.3f\n>esc:%06.3f\n",speed, current_speed, esc_output);
ESC.write(esc_output);
last_esc_write_ms = millis();
}
}
void speed_get()
{
static uint8_t _count_meas = 0;
static int _Drehregler = 0;
static unsigned long _last_read_ms = 0;
if(ser_speed == -1)
{
if( millis() - _last_read_ms > 25)
{
_last_read_ms = millis();
int maxDrehregler = 0;
int minDrehregler = 0;
int sumDrehregler = 0;
for(uint8_t i = 0; i<6;i++)
{
Drehregler = analogRead(POTI_PIN); // Dieser Befehl liest den Wert des Potentiometers am analogen Pin A0 aus und speichert ihn unter der Variablen "Drehregler". Der Wert liegt zwischen 0 und 1023.
if(i==0)
{
maxDrehregler = Drehregler;
minDrehregler = Drehregler;
}
else
{
if(Drehregler < minDrehregler)
{
minDrehregler = Drehregler;
}
if(Drehregler > maxDrehregler)
{
maxDrehregler = Drehregler;
}
}
sumDrehregler = sumDrehregler + Drehregler;
}
sumDrehregler = sumDrehregler - maxDrehregler - minDrehregler;
sumDrehregler = sumDrehregler/4;
#ifdef DUMMY_DATA
speed = 1000;
#else
speed = map(sumDrehregler, 0, MAX_POTI_VALUE, MIN_SPEED, MAX_SPEED); // Der "MAP-" Befehl wandelt den Messwert aus der Variablen "Drehregler" um, damit er am ESC verarbeitet werden kann. Der Zahlenbereich 0 bis 1023 wird dabei in einen Zahlenwert zwischen 0 und 180 umgewandelt.
#endif
}
}
else{
speed = ser_speed;
}
goal_speed = 1.0 * speed;
}
void data_init()
{
Serial.println("Init internal data ...");
@ -357,8 +296,6 @@ void data_init()
start_time = Store.get_int(EEPROM_NAME_START_EPOCHTIME );
Serial.printf("Machine runtime loaded from EPPROM: %lu seconds. Machine was started %s\n", run_time, capportal.localTime(start_time));
#endif
last_speed = 0;
speed = 0;
for (uint8_t i= 0; i < TIME_PER_ROUND_VALS; i++)
{
time_per_round_ms[i] = HALL_NR_TURN*MAX_TIME_PER_TURN_MS;
@ -383,7 +320,6 @@ void data_init()
}
#endif
AllData[i].act_update_ms = 0;
//AllData[i].prev_update_ms = 0;
}
}
@ -418,6 +354,7 @@ void data_check()
else
{
HallData[nr].value = HallData[nr].unit_factor / mid_time;
HallData[nr].value = HallData[nr].value > MAX_SPEED? MAX_SPEED:HallData[nr].value;
}
}
}
@ -462,8 +399,8 @@ void get_serial_cmd()
Serial.printf("Set ki to %f\n", ki);
}
else if(command.startsWith("speed=")){
ser_speed = command.substring(command.indexOf("=")+1).toDouble();
Serial.printf("Set speed to %f\n", ser_speed);
speed = command.substring(command.indexOf("=")+1).toDouble();
Serial.printf("Set speed to %f\n", speed);
}
else if(command.startsWith("kd=")){
derivative = 0.0;
@ -519,15 +456,19 @@ void get_serial_cmd()
void IRAM_ATTR ISR_HALL1()
{
const uint8_t hallnr = 0;
const unsigned long hall_ticks = HALL_NR_TURN * HALL_TICKS_PER_TURN;
const unsigned long hall_time = HALL_NR_TURN * MAX_TIME_PER_TURN_MS;
HallData[hallnr].ticks++;
HallData[hallnr].period_ticks++;
HallData[hallnr].timestamp = run_time;
// each 4 ticks is one turn
// so we calculate speed each 4 ticks... just in case we check for bigger ...
if(HallData[hallnr].period_ticks >= (HALL_NR_TURN * HALL_TICKS_PER_TURN)){
if(HallData[hallnr].period_ticks >= hall_ticks ){
unsigned long time_ms = millis();
unsigned long time_diff_ms = time_ms - HallData[hallnr].act_update_ms;
time_diff_ms= time_diff_ms > hall_time?hall_time:time_diff_ms;
HallData[hallnr].period_ticks = 0;
time_per_round_ms[time_per_round_pointer] = time_ms - HallData[hallnr].act_update_ms;
time_per_round_ms[time_per_round_pointer] = time_diff_ms;
HallData[hallnr].act_update_ms = time_ms;
time_per_round_pointer++;
time_per_round_pointer = time_per_round_pointer>TIME_PER_ROUND_VALS?0:time_per_round_pointer;

View File

@ -125,7 +125,7 @@ void Oled::show_values(int speed, int min_speed, int max_speed, volatile DataStr
_runtime = runtime; //runtime comes in in secs
_ipaddr = ipaddr;
show_page_header(ipaddr, page);
show_page_header(ipaddr);
show_speed(speed, min_speed, max_speed, _hall[0], _runtime, page );
show_halls(HallData, min(local_hall_count,hall_sensors_count), page);
show_page_footer(page);
@ -159,36 +159,25 @@ void Oled::show_page_footer(pages page)
display->drawHorizontalLine(_xpos+radius*2-2,63,128 - (_xpos+radius*2));
}
void Oled::show_page_header(String ipaddr, pages page)
void Oled::show_page_header(String ipaddr)
{
xpos = 0;
ypos = 0;
display->clear();
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_10);
switch(page)
if(ipaddr == "0.0.0.0")
{
case HALL1:
case HALL2:
display->drawString(0, ypos, "Measured numbers:");
display->setTextAlignment(TEXT_ALIGN_RIGHT);
break;
case SPEED:
default:
if(ipaddr == "0.0.0.0")
{
display->drawString(0, ypos, "No WiFi.");
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(128,ypos, "x");
}
else
{
display->drawString(0, ypos, "IP:" + ipaddr);
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(128,ypos, "Y");
display->drawString(124,ypos-2, "--");
}
break;
display->drawString(0, ypos, "No WiFi.");
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(128,ypos, "x");
}
else
{
display->drawString(0, ypos, "IP:" + ipaddr);
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(128,ypos, "Y");
display->drawString(124,ypos-2, "--");
}
display->drawHorizontalLine(0,ypos+12, 128);
ypos = ypos + 13;
@ -196,10 +185,34 @@ void Oled::show_page_header(String ipaddr, pages page)
void Oled::show_speed(int speed, int min_speed, int max_speed, double u_min, unsigned long runtime, pages page)
{
static char _runtime_str[26];
static unsigned long _runtime = 0;
uint8_t _ypos = ypos;
uint8_t _ypos_offset = 0;
display->setTextAlignment(TEXT_ALIGN_LEFT);
//display->setFont(ArialMT_Plain_10);
//display->drawString(1, _ypos, "Speed:");
//display->drawProgressBar(38, _ypos+4, 87, 5 , map(speed, min_speed, max_speed,0,100));
//display->setFont(ArialMT_Plain_10);
//_ypos=_ypos+9;
if(page == SPEED)
{
display->setFont(ArialMT_Plain_24);
_ypos_offset = 8;
}
else
{
static char _runtime_str[26];
static unsigned long _runtime = 0;
display->setFont(ArialMT_Plain_16);
}
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(83, _ypos, String(int(u_min)));
display->setFont(ArialMT_Plain_16);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(85,_ypos+_ypos_offset, "U/min");
_ypos=_ypos + 16 + _ypos_offset; //24;
if(page == SPEED)
{
if( _runtime != runtime || _runtime == 0)
{
_runtime = runtime;
@ -218,30 +231,18 @@ void Oled::show_speed(int speed, int min_speed, int max_speed, double u_min, uns
uint8_t _runtime_sec = _runtime;
sprintf(_runtime_str, "%01dy %02dm %01dw %01dd %02dh %02dm %02ds", _runtime_years, _runtime_month, _runtime_week, _runtime_days, _runtime_hour, _runtime_min, _runtime_sec);
}
uint8_t _ypos = ypos;
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_10);
display->drawString(1, _ypos, "Speed:");
display->drawProgressBar(38, _ypos+4, 87, 5 , map(speed, min_speed, max_speed,0,100));
display->setFont(ArialMT_Plain_10);
_ypos=_ypos+9;
display->setFont(ArialMT_Plain_24);
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(83, _ypos, String(u_min));
display->setFont(ArialMT_Plain_16);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(85,_ypos+8, "U/min");
_ypos=_ypos+24;
_ypos = _ypos + 5;
display->setFont(ArialMT_Plain_10);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64, _ypos, _runtime_str);
_ypos = _ypos + 10;
}
ypos = _ypos;
}
void Oled::show_halls(volatile DataStruct *HallData, uint8_t hall_sensor_count, pages page)
{
if(page == HALL1 || page == HALL2)
if(page == HALL1 || page == HALL2 || page == HALL3 || page == HALL4)
{
uint8_t hall_start = (page_nr-HALL1)*HALLS_PER_PAGE;
uint8_t hall_count = min(HALLS_PER_PAGE, (uint8_t)(hall_sensor_count-hall_start));