Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Encoder HIDScope MODSERIAL TextLCD mbed-dsp mbed
Fork of Main-script_groep7_V3 by
main.cpp
- Committer:
- lauradeheus
- Date:
- 2014-10-31
- Revision:
- 6:a7379a681adf
- Parent:
- 5:4842219cb77c
- Child:
- 7:7e3e183bf063
File content as of revision 6:a7379a681adf:
/********************************************/
/* */
/* BRONCODE GROEP 7, MODULE 9, 2014 */
/* *-THE SLAP-* */
/* */
/* -Anne ten Dam */
/* -Laura de Heus */
/* -Moniek Strijdveen */
/* -Bart Arendshorst */
/* -Peter Bartels */
/********************************************/
/*
#include voor alle libraries
*/
#include "TextLCD.h"
#include "mbed.h"
#include "encoder.h"
#include "HIDScope.h"
#include "PwmOut.h"
#include "arm_math.h"
/*
#define vaste waarden
*/
/*definieren pinnen Motor 1*/
#define M1_PWM PTA5
#define M1_DIR PTA4
#define M2_PWM PTC8
#define M2_DIR PTC9
/*Definieren minimale waarden PWM per motor*/
#define PWM1_min_50 0.529 /*met koppelstuk!*/
#define PWM2_min_30 0.529 /*aanpassen! Klopt nog niet met koppelstuk*/
/*Definieren om de hoeveel seconden er gegevens naar de HID-scope gestuurd worden.*/
#define TSAMP 0.005
#define K_P (5)
#define K_I (0.1 * TSAMP)
#define K_D (0)
//#define K_D (0.0005 /TSAMP)
#define I_LIMIT 100.
#define PI 3.1415926535897
#define lengte_arm 0.5
/*
Geef een naam aan een actie en vertel welke pinnen hiervoor gebruikt worden.
*/
TextLCD lcd(PTD2, PTA12, PTB2, PTB3, PTC2, PTA13, TextLCD::LCD16x2); // rs, e, d4-d7
Encoder motor1(PTD3,PTD1);
Encoder motor2(PTD5, PTD0);
PwmOut pwm_motor1(M1_PWM);
PwmOut pwm_motor2(M2_PWM);
DigitalOut motordir1(M1_DIR);
DigitalOut motordir2(M2_DIR);
DigitalOut LEDGREEN(LED_GREEN);
DigitalOut LEDRED(LED_RED);
Serial pc(USBTX,USBRX);
HIDScope scope(3);
AnalogIn emg(PTB1);
/*
definieer namen aan var, float, int, static float, uint8_t, uint16_t etc. en geef ze eventueel een waarde
*/
Ticker statemachine;
Ticker screen;
arm_biquad_casd_df1_inst_f32 lowpass_1; //2e orde lowpass biquad butterworthfilter 99Hz
arm_biquad_casd_df1_inst_f32 lowpass_2; //2e orde lowpass biquad butterworthfilter 3Hz
arm_biquad_casd_df1_inst_f32 highpass; //2e orde highpass biquad butterworthfilter 20Hz
arm_biquad_casd_df1_inst_f32 notch; //2e orde lowpass biquad butterworthfilter 50Hz
int previous_herhalingen = 0;
int current_herhalingen = 0;
int PWM2_percentage = 100;
int aantal_rotaties_1 = 10;
int aantalcr_1 = 1600;
int aantalcr_2 = 960;
int beginpos_motor1;
int beginpos_motor1_new;
int beginpos_motor2;
int beginpos_motor2_new;
int previous_pos_motor1 = 0;
int current_pos_motor1;
int EMG = 1;
int delta_pos_motor1_puls;
int aantal_pieken;
int doel;
bool aanspan;
void clamp(float * in, float min, float max);
volatile bool looptimerflag;
int16_t gewenste_snelheid = 2;
int16_t gewenste_snelheid_rad = 4;
int16_t gewenste_snelheid_rad_return = 1;
float pid(float setpoint, float measurement);
float pos_motor1_rad;
float PWM1_percentage = 0;
float delta_pos_motor1_rad;
float snelheid_motor1_rad;
float snelheid_arm_ms;
float PWM1;
float PWM2;
float Speed_motor1;
float Speed_motor1rad;
float setpoint = 0;
float prev_setpoint = 0;
float lowpass_1_const[] = {0.978030479206560 , 1.956060958413119 , 0.978030479206560 , -1.955578240315036 , -0.956543676511203};
float lowpass_1_states[4];
float lowpass_2_const[] = {0.002080567135492 , 0.004161134270985 , 0.002080567135492 , 1.866892279711715 , -0.875214548253684};
float lowpass_2_states[4];
float highpass_const[] = {0.638945525159022 , -1.277891050318045 , 0.638945525159022 , 1.142980502539901 , -0.412801598096189};
float highpass_states[4];
float notch_const[] = {0.978048948305681 , 0.000000000000000 , 0.978048948305681 , 0.000000000000000 , -0.956097896611362};
float notch_states[4];
float emg_filtered;
float emg_max = 0;
float emg_treshhold_laag = 0;
float emg_treshhold_hoog = 0;
//HIDScope scope(6);
enum state_t {RUST, ARM_KALIBRATIE, EMG_KALIBRATIE, METEN_RICHTING, METEN_HOOGTE, INSTELLEN_RICHTING, SLAAN, RETURN2RUST}; //verschillende stadia definieren voor gebruik in CASES
state_t state = RUST;
//functies die vanuit de statemachinefunction aangeroepen kunnen worden
void rust() {
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
}
void arm_kalibratie() {
//voor nu om de loop te doorlopen wordt onderstaande code gebruikt. Nogmaal gesproken moet er gewacht worden op een 'hoog' signaal van een knop
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
motor1.setPosition(0);
motor2.setPosition(0);
}
void pieken_tellen(){
if (emg_filtered>=emg_treshhold_hoog)
{
aanspan=true; //maak een variabele waarin je opslaat dat het signaal hoog is.
}
if (aanspan==true && emg_filtered<=emg_treshhold_laag)//== ipv =, anders wordt aanspan true gemaakt
{
aanspan=false;
aantal_pieken++;
doel = aantal_pieken-((aantal_pieken/3)*3)+1;
}
}
void emg_filtering() {
uint16_t emg_value;
float emg_value_f32;
emg_value = emg.read_u16(); // read direct ADC result, converted to 16 bit integer (0..2^16 = 0..65536 = 0..3.3V)
emg_value_f32 = emg.read();
arm_biquad_cascade_df1_f32(&highpass, &emg_value_f32, &emg_filtered, 1 );
arm_biquad_cascade_df1_f32(&lowpass_1, &emg_filtered, &emg_filtered, 1 );
arm_biquad_cascade_df1_f32(¬ch, &emg_filtered, &emg_filtered, 1);
emg_filtered = fabs(emg_filtered);
arm_biquad_cascade_df1_f32(&lowpass_2, &emg_filtered, &emg_filtered, 1 );
scope.set(0,emg_value); //uint value
scope.set(1,emg_filtered); //processed float
scope.set(2,doel);
scope.send();
if(state!=EMG_KALIBRATIE)
{
pieken_tellen();
}
}
void emg_max_meting(){
emg_filtering();
if (emg_filtered>=emg_max)
{
emg_max=emg_filtered;
}
emg_treshhold_laag = 0.3*emg_max;
emg_treshhold_hoog = 0.7*emg_max;
}
void emg_kalibratie() {
if(emg_filtered>=0.05){
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
}
if(current_herhalingen<=1000)
{
emg_max_meting();
}
}
void meten_richting() {
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
}
void meten_hoogte() {
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
}
void instellen_richting() {
current_herhalingen = previous_herhalingen + 1; previous_herhalingen = current_herhalingen;
}
void GotoPosition (float position_setpoint_rad, float speed_radpersecond) {
current_pos_motor1 = motor1.getPosition(); //bekijk na elke 0.005s wat de huidige 'waarde' van de encoder is
//delta_pos_motor1_puls = current_pos_motor1 - previous_pos_motor1; //Bereken wat het verschil in waarde is voor het berekenen van de snelheid(puls)
pos_motor1_rad = current_pos_motor1/(1600/(2*PI)); //echte waarde omrekenen naar rad voor (positie) PID regelaar
//delta_pos_motor1_rad = delta_pos_motor1_puls/(1600/(2*PI)); //delta waarde omrekenen naar rad voor snelheidsbepaling (rad)
//snelheid_motor1_rad = delta_pos_motor1_rad / TSAMP; //rad delen door TSAMP om rad/s te verkrijgen
//snelheid_arm_ms = snelheid_motor1_rad * lengte_arm; //deze waarde maar lengte van de arm om de snelheid van het uiteinde van die arm te verkrijgen
//scope.set(0, snelheid_motor1_rad);
previous_pos_motor1 = current_pos_motor1; //sla de huidige waarde op als vorige waarde.
//nu gaan we positie regelen i.p.v. snelheid.
if (fabs(pos_motor1_rad - position_setpoint_rad) <= 0.05) //if position error < ...rad, then stop.
{
speed_radpersecond = 0;
setpoint = pos_motor1_rad;
current_herhalingen = previous_herhalingen + 1;
previous_herhalingen = current_herhalingen;
pc.printf("stop\n\r");
PWM1_percentage = 0;
}
else if(pos_motor1_rad - position_setpoint_rad < 0)
{
setpoint = prev_setpoint +( TSAMP * speed_radpersecond);
PWM1_percentage = pid(setpoint, pos_motor1_rad);
}
else
{
setpoint = prev_setpoint -( TSAMP * speed_radpersecond);
PWM1_percentage = pid(setpoint, pos_motor1_rad);
}
/*new_pwm = (setpoint - motor1.getPosition())*.001; -> P action*/
pc.printf("%f\n\r",PWM1_percentage);
//scope.set(1, setpoint-pos_motor1_rad);
if (PWM1_percentage < -100)
{
PWM1_percentage = -100;
}
else if (PWM1_percentage >100)
{
PWM1_percentage =100;
}
if(PWM1_percentage < 0)
{
motordir1 = 1;
}
else
{
motordir1 = 0;
}
pwm_motor1.write(abs(PWM1_percentage/100.));//abs(((1-PWM1_min_50)/100)*PWM1_percentage + PWM1_min_50));
//scope.set(5, abs(((1-PWM1_min_50)/100)*PWM1_percentage + PWM1_min_50));
prev_setpoint = setpoint;
//scope.send();
}
float pid(float setpoint, float measurement)
{
float error;
static float prev_error = 0;
float out_p = 0;
static float out_i = 0;
float out_d = 0;
error = (setpoint-measurement);
out_p = error*K_P;
out_i += error*K_I;
out_d = (error-prev_error)*K_D;
clamp(&out_i,-I_LIMIT,I_LIMIT);
prev_error = error;
//scope.set(2, out_p);
//scope.set(3, out_i);
//scope.set(4, out_d);
return out_p + out_i + out_d;
}
void clamp(float* in, float min, float max) // "*" is een pointer (verwijst naar het adres waar een variebele instaat). Dus je slaat niet de variabele op
// maar de locatie van de variabele.
{
*in > min ? /*(*/*in < max? /*niets doen*/ : *in = max/*)*/: *in = min; // a ? b : c --> als a waar is, dan doe je b, en anders c
// *in = het getal dat staat op locatie van in --> waarde van new_pwm
}
void statemachinefunction()
{
switch(state) {
case RUST: {
rust();
/*voorwaarde wanneer hij door kan naar de volgende case*/
if (current_herhalingen == 100 && EMG == 1)
{
current_herhalingen = 0;
previous_herhalingen = 0;
state = ARM_KALIBRATIE;
EMG = 0;
}
break;
/*bepalen hoe je zorgt dat je maar 1x de kalibraties uitvoerd! (Of eventueel de arm kalibratie elke keer!!)*/
//if (metingstatus<5);
// state = ARMKALIBRATIE;
//if (metingstatus==5);
// state = METEN_RICHTING;
//break;
//}
}
case ARM_KALIBRATIE:
{
arm_kalibratie();
if (current_herhalingen == 100)
{
current_herhalingen = 0;
previous_herhalingen = 0;
state = EMG_KALIBRATIE;
motor1.setPosition(0);
motor2.setPosition(0);
pwm_motor1.period_us(100);
pwm_motor2.period_us(100);
}
break;
}
case EMG_KALIBRATIE:
{
emg_kalibratie();
if (current_herhalingen >=1000)
{
state = METEN_RICHTING;
current_herhalingen = 0;
previous_herhalingen = 0;
}
break;
}
case METEN_RICHTING:
{
meten_richting();
if (current_herhalingen == 100)
{
state = METEN_HOOGTE;
current_herhalingen = 0;
previous_herhalingen = 0;
}
break;
}
case METEN_HOOGTE:
{
meten_hoogte();
if (current_herhalingen == 100)
{
state = INSTELLEN_RICHTING;
current_herhalingen = 0;
previous_herhalingen = 0;
}
break;
}
case INSTELLEN_RICHTING:
{
instellen_richting();
if (current_herhalingen == 100)
{
state = SLAAN;
current_herhalingen = 0;
previous_herhalingen = 0;
}
break;
}
case SLAAN:
{
GotoPosition(1.5 ,8);
if (current_herhalingen == 100)
{
state = RETURN2RUST;
current_herhalingen = 0;
previous_herhalingen = 0;
prev_setpoint =0;
setpoint =0;
}
break;
}
case RETURN2RUST:
{
GotoPosition(0,2);
if (current_herhalingen == 100)
{
state = RUST;
current_herhalingen = 0;
previous_herhalingen = 0;
}
break;
}
default: {
state = RUST;
}
}//switch(state)
}//void statemachinefunction
void screenupdate(){
if(state==RUST){
lcd.cls();
lcd.locate(0,0);
lcd.printf("V.I.C.T.O.R.Y."); //regel 1 LCD scherm
lcd.locate(0,1);
lcd.printf(" GROEP 7 ");
}
else if(state==EMG_KALIBRATIE){
lcd.cls();
lcd.locate(0,0);
lcd.printf("Max. aanspannen");
if(current_herhalingen<=200){
lcd.locate(0,1);
lcd.printf("nog 5 sec.");
}
else if(current_herhalingen<=400){
lcd.locate(0,1);
lcd.printf("nog 4 sec.");
}
else if(current_herhalingen<=600){
lcd.locate(0,1);
lcd.printf("nog 3 sec.");
}
else if(current_herhalingen<=800){
lcd.locate(0,1);
lcd.printf("nog 2 sec.");
}
else if(current_herhalingen<=1000){
lcd.locate(0,1);
lcd.printf("nog 1 sec.");
}
}
else{
lcd.cls();
lcd.printf("state %d", state); //hier nog aan toevoegen hoe je de 'waarde', dus eigenlijk tekst, die opgeslagen staat in state kan printen.
}
}
int main(){
pc.baud(115200);
arm_biquad_cascade_df1_init_f32(&lowpass_1,1 , lowpass_1_const, lowpass_1_states);
arm_biquad_cascade_df1_init_f32(&highpass,1 , highpass_const, highpass_states);
arm_biquad_cascade_df1_init_f32(¬ch,1 , notch_const, notch_states);
arm_biquad_cascade_df1_init_f32(&lowpass_2,1 , lowpass_2_const, lowpass_2_states);
statemachine.attach(&statemachinefunction, TSAMP); // the address of the function to be attached (flip) and the interval (2 seconds)
screen.attach(&screenupdate, 0.2);
while(1);
}
