Qsort() is messing with my entire Code!!!

Joined
Apr 25, 2022
Messages
2
Reaction score
0
HI Guys I have a problem with my selfmade Torquemeter
Since I use qsort() to detect the lowest and the highest meausurement my Programm behaves very diffrent then before... does anybody has a clue why ?
Just to simplify my Project I use an IR-Sensor that gets me a 1 when the disk has spinned one time. I recognize the edge of the Signal with an Interrupt and Reset the Timer0+CounterH ( to make an 16bit one) and on the second edge I save the measured value. At the same time i drive the Motor with a PWM (Timer1) so i can regulate the motors rotation speed on a stedy value.
if you have any questions just ask!
Im glad for every response....
I hope someone can help me
Code:
/*
* Projektname: Drehzahlmesser
* Filename: main.cpp
* Created: 07.03.2022 10:07:53
* Author : Mika Hug
* Kandidaten nr: 3472
* Funktion: Drehzahlmesser*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lcd_lib.h"
#include "keyMonitor.h"
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//##############################################################################
// Definitionen
//##############################################################################
#define F_CPU 8000000UL // CPU Frequenz auf 8MHz festlegen
#define PIEZO_PIN 0x08 // Piezo Pin festlegen
#define LED_ROT_PIN 0x10 // LED Rot Pin festlegen
#define LED_GRUEN_PIN 0x02 // LED Grün Pin festlegen
#define BIT_RESET_PIN 0x40 // BIT_Reset Pin festlegen Achtung!: Low-aktiver Reset
#define SENSOR_ENABLE_PIN 0x01 // Infrarotsensorspeisungs Pin festlegen
#define TOLERANZ 10 // RPM Toleranz
#define PIEZO_TOLERANZ 50 // Toleranz des Piezo beepers festlegen
#define RPM58HZ 3500 // PIEZO @RPM 3500 / @58.33Hz
#define RPM133HZ 8000
#define T 63999 // BIT @RPM 8000 / @133.333Hz
#define TMAX 47999
#define TMIN 56399
#define TMOTOREIN 55119
#define TMOTORMAX 12599
#define TOLERANZ 10
#define FLOAT 8000.0000
#define FLOAT2 3500.0000
typedef enum
{
BIT,
MODUS,
MANUELL,
AUTOMATISCH3500,
AUTOMATISCH8000,

} status_t;
typedef enum
{
ENTRY,
EXIT,

} phase_t;
//##############################################################################

//##############################################################################
//Globale Variablen für Interrupt Service Routine
//##############################################################################
volatile uint16_t periodendauer_us = false; //Messzeit in µs als 16bit unsigned integer initialisieren und nullen
volatile bool ersteflanke = false; //flanke1 als Wahrheitszustand initialisieren und nullen
volatile bool zweiteflanke = false; //flanke2 als Wahrheitszustand initialisieren und nullen
volatile bool anpassung = false;
volatile float messaverage = 0;
volatile uint8_t CounterH = 0;
volatile uint16_t Timer = 0;
int null = 0;
int bit = true;
//##############################################################################
// Funktionsimplementationen
float messung(void);
void InitSystem(void);
void Initinterrupt(void);
void init_ADC(void);
void InitTimer(void);
uint16_t ADC_READ(void);
long Werteverteilung(long x,long in_min,long in_max, long out_min, long out_max);
bool hasStateChanged(status_t* currentState, phase_t phase);
int floatcomp(const void* elem1, const void* elem2);
key_t t_manuell;
key_t t_automatisch8000;
key_t t_automatisch3500;
key_t t_reset;
//##############################################################################

int main(void)
{
InitSystem();
uint16_t Anzahl_bits = 0;
registerKey(&PINA,1,POSITIVE,&t_automatisch8000);
registerKey(&PINA,2,POSITIVE,&t_automatisch3500);
registerKey(&PINA,3,POSITIVE,&t_manuell);
registerKey(&PINA,4,POSITIVE,&t_reset);
InitSystem();
Initinterrupt();
PORTD|= BIT_RESET_PIN; // BIT Pin auf HIGH schalten weil Low aktiv //System initialisieren
lcdInit();
lcdEnableBacklight(true);
status_t status = BIT ;
while (1)
{
serviceKeyMonitor();
switch(status)
{
case BIT:
if(hasStateChanged(&status,ENTRY))
{

}
if (bit == 1)
{
messung();
}
else
{
PORTD |= SENSOR_ENABLE_PIN;
status = MODUS;
}
if(hasStateChanged(&status,EXIT))
{

}
break;
case MODUS:
if(hasStateChanged(&status,ENTRY))
{
OCR1A = TMIN;
lcdClear();
lcdSetCursor(1,0);
printf("Modus eingeben");
}
if(hasTriggered(&t_automatisch8000,RISING,0))
{
status = AUTOMATISCH8000;
}
if(hasTriggered(&t_manuell,RISING,0))
{
status = MANUELL;
}
if(hasTriggered(&t_automatisch3500,RISING,0))
{
status = AUTOMATISCH3500;
}
if(hasStateChanged(&status,EXIT))
{
lcdClear();
}
break;
case AUTOMATISCH3500:
if(hasStateChanged(&status,ENTRY))
{
lcdClear();
OCR1A = TMOTOREIN;
}
if(hasTriggered(&t_reset,RISING,0))
{
status = MODUS;
}
else
{
messung();
if(messaverage < RPM58HZ)
{
OCR1A--;
_delay_ms(50);
if (messaverage>RPM58HZ)
{
OCR1A++;
}
}
else if(messaverage > RPM58HZ)
{
OCR1A++;
_delay_ms(50);
if (messaverage<RPM58HZ)
{
OCR1A--;
}
}
else if(messaverage == RPM58HZ)
{
//do nothing
}
}
if(hasStateChanged(&status,EXIT))
{

}
break;

case AUTOMATISCH8000:
if(hasStateChanged(&status,ENTRY))
{
lcdClear();
OCR1A = TMOTOREIN;
while(messung()< 7500)
{
_delay_ms(200);
OCR1A = OCR1A - 10;
}
}
if(hasTriggered(&t_reset,RISING,0))
{
status = MODUS;
}
else
{
if((messung() < RPM133HZ)&&(OCR1A>TMAX))
{
OCR1A--;
_delay_ms(100);
}
if((messung() > RPM133HZ)&&(OCR1A<TMIN))
{
OCR1A++;
_delay_ms(100);
}
}
if(hasStateChanged(&status,EXIT))
{

}
break;
case MANUELL:
if(hasStateChanged(&status,ENTRY))
{
lcdClear();
Anzahl_bits = ADC_READ();
while(Anzahl_bits != 0)
{
Anzahl_bits = ADC_READ();
lcdClear();
lcdSetCursor(1,0);
printf("Pot auf 0 einst.");
lcdSetCursor(2,0);
printf("Pot wert:%u",Anzahl_bits);
_delay_ms(500);
}
lcdClear();
lcdSetCursor(1,0);
printf("I.O.");
_delay_ms(500);
lcdClear();
}
if(hasTriggered(&t_reset,RISING,0))
{
status = MODUS;
}
Anzahl_bits = ADC_READ();
OCR1A = Werteverteilung(Anzahl_bits,1023,0,TMOTORMAX,TMOTOREIN);
messung();
if(hasStateChanged(&status,EXIT))
{

}
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
//Messen
//////////////////////////////////////////////////////////////////////////

float messung(void)
{
float messwert[6]; //Messwert Array als float initialisieren mit 6 Feldern
messwert[0] = false; // Feld 0 nullen
messwert[1] = false; // Feld 1 nullen
messwert[2] = false; // Feld 2 nullen
messwert[3] = false; // Feld 3 nullen
messwert[4] = false; // Feld 3 nullen
messwert[5] = false;
messwert[6] = false;
ersteflanke = false; // Flanke 1 nullen
zweiteflanke = false; // Flanke 2 nullen
periodendauer_us = false;
messaverage = 0;
//bool schlaufe = 1;
sei();
while (1)
{

if(((ersteflanke&&zweiteflanke) == true)&&(messwert[0]==0))
{
//cli();
messwert[0] = periodendauer_us; //messwertArray Feld null -> Messung einlesen
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//sei();
}
/*else if ((TCNT2<<8)>0xF000)
{
//break;
cli();
lcdSetCursor(1,0);
printf("no signal");
schlaufe = 0;
return 0;
}*/
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[0]!=0))
{
//cli();
messwert[1] = periodendauer_us;
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//sei();
}
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[1]!=0))
{
//cli();

messwert[2] = periodendauer_us;
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//sei();
}
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[2]!=0))
{
//cli();
messwert[3] = periodendauer_us; //messwertArray Feld 2 -> Messung einlesen
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//return messwert [2];
//sei();
}
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[3]!=0))
{
//cli();
messwert[4] = periodendauer_us; //messwertArray Feld 2 -> Messung einlesen
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//sei();
}
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[4]!=0))
{
//cli();
messwert[5] = periodendauer_us; //messwertArray Feld 2 -> Messung einlesen
ersteflanke = false; // Flanke1 zurücksetzen
zweiteflanke = false; // Flanke2 zurücksetzen
periodendauer_us = false; //Zeitmessung zurücksetzen
//sei();
}
if(((ersteflanke&&zweiteflanke)== true)&&(messwert[5]!=0))
{
cli();
messwert[6] = periodendauer_us;
//printf("funk");
qsort(messwert,7,sizeof(float),floatcomp);
//_delay_ms(1000);
//printf("tioniert");
messaverage= 60*(1000000/((messwert[1]+messwert[2]+messwert[3]+messwert[4]+messwert[5])/5));
messaverage = round(messaverage);
lcdClear();
lcdSetCursor(1,0);
printf("%.0f RPM",messaverage);
messwert[0] = false; // Feld 0 nullen
messwert[1] = false; // Feld 1 nullen
messwert[2] = false; // Feld 2 nullen
messwert[3] = false; // Feld 3 nullen
messwert[4] = false; // Feld 3 nullen
messwert[5] = false;
messwert[6] = false;
if(messaverage == RPM133HZ) //wenn RPM = 7990-8010
{

PORTD |= LED_GRUEN_PIN; //LED Grün ein
PORTD &=~ LED_ROT_PIN;
if(bit == true) //Im BIT Zustand folgendes ausführen
{
lcdSetCursor(2,0); // Cursor des LCD auf 2.Zeile setzen
printf("BIT I.O."); //"BIT I.O." auf LCD schreiben
bit = false; // BIT abgeschlossen
PORTD &=~BIT_RESET_PIN; // Taktgenerator deaktivieren
PORTD |= SENSOR_ENABLE_PIN; // Infrarot Sensor aktivieren
_delay_ms(3000); // 3s warten damit die nachricht gelesen werdên kann
PORTD &=~ LED_GRUEN_PIN; //LED grün aus
PORTD |= LED_ROT_PIN; //LED rot ein
lcdClear(); // 0 RPM schreiben
}
//_delay_ms(250);
break;
}

else if((messaverage != RPM133HZ)&&(messaverage != 0)) //wenn RPM = sonstige Zahl
{
PORTD &=~ LED_GRUEN_PIN; //LED Grün aus
PORTD |= LED_ROT_PIN; //State auf RPM_ROT
if(bit == true) //Im BIT Zustand folgendes ausführen
{
lcdSetCursor(2,0); // Cursor des LCD auf 2.Zeile setzen
printf("BIT Fail!"); //"BIT Fail check!" auf LCD schreiben
} //LED Rot ein
//_delay_ms(250);
break;
}
}
}
return messaverage; //End Switch
}
//End messung

//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
// Interrupt Service Routine
//______________________________________________________________________________
ISR(TIMER0_OVF_vect)
{
CounterH ++;
}
ISR(INT0_vect)
{

if(ersteflanke == false) // wenn noch keine Flanke gekommen ist
{ // Erste Flanke gekommen
ersteflanke = true;
TCNT0 = 0;
CounterH = 0;
}

else
{
//periodendauer_us = TCNT1;
periodendauer_us = (TCNT0)|(CounterH<<8);
zweiteflanke = true;
//serviceKeyMonitor();
}
}
//______________________________________________________________________________
//##############################################################################
// Funktionsimplementationen
//##############################################################################

void InitSystem(void)
{
//Ports initialisieren
DDRB = 0xFF; //Alle Pins an Port A sind Eingänge --> Signal
DDRA = 0x00; //Alle Pins an Port A sind Eingänge --> LCD
DDRD = 0xFB; //Pin3/0x04 -> Eingang für Interrupt Pin1+2&Pin4-6 als Ausgänge definieren
InitTimer(); //Timer initialisieren
Initinterrupt(); // Interrupt initialisieren
init_ADC();
lcdInit();
lcdEnableBacklight(true);
init_ADC();
}
void InitTimer(void)
{
TCCR0 = 1<<CS01;
TIMSK = 1<<TOIE0;
TCCR1A = (1<<WGM11)|(1<<COM1A0)|(1<<COM1A1);
TCCR1B = (1<<CS10)|(1<<WGM12)|(1<<WGM13);
ICR1 = T;
OCR1A = TMIN;
}
void Initinterrupt(void)
{
MCUCR = (1<<ISC00|1<<ISC01); // auf positive Flanke Triggern
GICR = 1<< INT0; // Interrupt 0 Enablen
}
void init_ADC(void)
{
ADMUX = (1<<REFS0);
ADCSRA = (1<<ADEN);
}
uint16_t ADC_READ(void)
{
_delay_ms(10);
ADCSRA |= (1<<ADSC);
while(ADCSRA &(1<<ADSC));
//warten
return ADCW;
}
long Werteverteilung(long x,long in_min,long in_max, long out_min, long out_max)
{
long result = ((x - in_min) * (out_max - out_min) / (in_max - in_min))+out_min;
return result;
}
int floatcomp(const void* elem1, const void* elem2)
{
if(*(const float*)elem1 < *(const float*)elem2)
return -1;
return *(const float*)elem1 > *(const float*)elem2;
}
bool hasStateChanged(status_t* currentState, phase_t phase)
{
static status_t lastState=0xFF;
bool stateHasChanged = false;
if (*currentState != lastState)
{
stateHasChanged = true;
if (phase == ENTRY)
{
lastState = *currentState;
}
}
return stateHasChanged;
}
 
Last edited:

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top