C++ MBed klasse-vraagje

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • jctjepkema
  • Registratie: Mei 2011
  • Laatst online: 04-10 15:47
Hoi, beginner/n00b vraagje, volgens mij zit ik goed hier of hoort dit meer thuis in het Elektro forum?

Ik heb in mijn programma een klasse gemaakt. de klasse readFunction.

als ik deze open: readFunction blabla (Pin Tx, Pin Rx, Pin transistor);

in class readFunction creëer ik dus een serial object(volgens mij heet dat een object?) deze staat aangeroepen in de public: Serial serial;

nu wil ik een interrupt hebben, zodat wanneer hij een serial bericht binnen krijgt hij de blabla.read() functie uitvoert.

Ik zou niet weten hoe ik dit moet doen, ik weet dat je een serial interrupt kan aanmaken d.m.v. serial.attach(je_functie); dit had ik al werkend maar ik probeer het nu te verwerken in een klasse.

Code:

C++: main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "mbed.h"
#include "functions.h"


readFunction projector(PA_9, PA_10, PA_8);/*Tx, Rx, NPN transistor*/
Serial ctrl     (PA_2, PA_3);

float waitTime = 0;
void leesfunctie();
int main() 
{
    serial.attach(readFunction.read());//dit werkt dus niet en dat is natuurlijk erg logisch. 
    for(;;);
}

C++: functions.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "mbed.h"

class readFunction{
    float waitTime;
    bool already_on;
    public:
        readFunction(PinName Tx, PinName Rx, PinName out);
        //float waitTime = 0;
        //bool already_on = false;

        void read(void);
        
        Serial      serial;
        DigitalOut  npn;
    private:
};

C++: functions.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "mbed.h"
#include "functions.h"

readFunction::readFunction (PinName Tx,
                            PinName Rx,
                            PinName out) : serial(Tx, Rx), npn(out) {
                                
    serial.format(/* bits: */ 9, /* Parity: */ SerialBase::Even, /* Stop bits: */ 1);

    //data settings
    already_on = false;
    waitTime =0;
    //end data settings
    npn.write(0);
}
void readFunction::read(void) {
/*onbelangrijke code voor het verhaal*/
}


Hoe zou ik dit kunnen doen? Is het uberhaupt mogelijk of gaat het tegen de richtlijnen in? En hoe moet het dan wel?

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
De interrupt handler kan op deze manier niet weten op welk object hij de functie moet aanroepen : als deze static is werkt het waarschijnlijk wel.

Je zult dus op 1 of andere manier de globale call moeten doorsturen naar je "echte" object, bv door een vrije/static functie aan je interrupt te hangen en vanaf daar doorsturen naar je readFunction instantie.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • jctjepkema
  • Registratie: Mei 2011
  • Laatst online: 04-10 15:47
farlane schreef op woensdag 3 mei 2017 @ 22:11:
De interrupt handler kan op deze manier niet weten op welk object hij de functie moet aanroepen : als deze static is werkt het waarschijnlijk wel.

Je zult dus op 1 of andere manier de globale call moeten doorsturen naar je "echte" object, bv door een vrije/static functie aan je interrupt te hangen en vanaf daar doorsturen naar je readFunction instantie.
Ik volg niet helemaal wat je bedoelt, bedoel je dat ik een static functie zou moeten aanmaken, waarbinnen ik dan de projector.read(); zou moeten aanspreken, en in de klasse weer een serial.attach(naar die functie)?

Want dan krijg ik "defunctie" is unidentified error 20;

Zou je een klein voorbeeldje kunnen gebruiken?

Acties:
  • 0 Henk 'm!

  • expor
  • Registratie: Juni 2005
  • Laatst online: 01-10 22:53
In je readFunction constructor zou het volgende moeten werken:

C++:
1
serial.attach(this, &readFunction::read); 

AMD 5800X3D | 16gb DDR 4 @ 3800/14 | 4070 Ti | 1TB Samsung Evo 970, 1TB Samsung Evo 860, 512MB Crucial


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
jctjepkema schreef op donderdag 4 mei 2017 @ 08:25:
[...]
Ik volg niet helemaal wat je bedoelt, bedoel je dat ik een static functie zou moeten aanmaken, waarbinnen ik dan de projector.read(); zou moeten aanspreken, en in de klasse weer een serial.attach(naar die functie)?

Zou je een klein voorbeeldje kunnen gebruiken?
Ik zal er 1 gebruiken :) :
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ReadFunction{

public:
    static void serialIntHandler(void){

        static ReadFunction rd;

        rd.read();
    }

private:
    void read( ){
        // serial.stuff() ?
    }
};

int main(){
    serial.attach( ReadFunction::serialIntHandler );
}


Dit is dan dus de variant waarbij je de "globale" read handler als static functie in je ReadFunction class hebt, maar je kunt er ook een vrij functie van maken natuurlijk.

[edit]
Als ik hier kijk heb je ook een mogelijkheid om direct member functions te gebruiken. De mapping van vrije functie -> member functie wordt dan voor je gedaan.

Pas wel op dat je ReadFunction object niet out of scope gaat (door 'em static te maken bijvoorbeeld) , want dan is er geen object meer om de member functie op aan te roepen.

code:
1
2
3
4
5
ReadFunction rf;

int main(){
    serial.attach( callback( &rf, &ReadFunction::read ), Serial::RxIrq );
}

[ Voor 25% gewijzigd door farlane op 04-05-2017 13:27 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • jctjepkema
  • Registratie: Mei 2011
  • Laatst online: 04-10 15:47
farlane schreef op donderdag 4 mei 2017 @ 12:47:
[...]


Ik zal er 1 gebruiken :) :
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ReadFunction{

public:
    static void serialIntHandler(void){

        static ReadFunction rd;

        rd.read();
    }

private:
    void read( ){
        // serial.stuff() ?
    }
};

int main(){
    serial.attach( ReadFunction::serialIntHandler );
}


Dit is dan dus de variant waarbij je de "globale" read handler als static functie in je ReadFunction class hebt, maar je kunt er ook een vrij functie van maken natuurlijk.

[edit]
Als ik hier kijk heb je ook een mogelijkheid om direct member functions te gebruiken. De mapping van vrije functie -> member functie wordt dan voor je gedaan.

Pas wel op dat je ReadFunction object niet out of scope gaat (door 'em static te maken bijvoorbeeld) , want dan is er geen object meer om de member functie op aan te roepen.

code:
1
2
3
4
5
ReadFunction rf;

int main(){
    serial.attach( callback( &rf, &ReadFunction::read ), Serial::RxIrq );
}
Thanks! Ik was nog wat verder gaan googlen, en ik heb in de functions.cpp bij de readFunction::readFunction de volgende regel geplaatst:

serial.attach(this, &readFunction::read);

Nu werkt ie ook, ik zie dat jij een callback gebruikt, wat houd dat precies in ten opzichte van this?

Acties:
  • 0 Henk 'm!

  • expor
  • Registratie: Juni 2005
  • Laatst online: 01-10 22:53
Dat ligt eraan vanaf waar je de functie wil binden. In geval de oplossing die ik gaf (en die je zelf ook had gevonden) doe je dit vanuit de class die the handler implementeert, vandaar 'this'. De oplossing van farlane is vanuit main gezien. Dan maak je dus eerst het object aan, en bind je vanaf daar een member functie van dat object. Het eerste argument van attach() is in dat geval dus een pointer naar het object dat de handler implementeert.

Edit: Ik zie nu pas waar je naar refereerde met die callback, dat is niet per see nodig voor zover ik het zie in de API. Het derde argument, RxIrq is overigens default al gezet en is dus optioneel.

[ Voor 18% gewijzigd door expor op 04-05-2017 15:10 ]

AMD 5800X3D | 16gb DDR 4 @ 3800/14 | 4070 Ti | 1TB Samsung Evo 970, 1TB Samsung Evo 860, 512MB Crucial


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
jctjepkema schreef op donderdag 4 mei 2017 @ 14:23:
Nu werkt ie ook, ik zie dat jij een callback gebruikt, wat houd dat precies in ten opzichte van this?
De callback klasse en this hebben niets met elkaar te maken, maar met combinatie van parameters die je gebruikt ( this en de pointer-naar-memberfunctie ) kan een callback object worden gemaakt.

Dat wordt in jouw geval gedaan door een functie van de SerialBase class, die hetzelfde doet als ik. Die functie is gemarkeerd als deprecated, vandaar dat ik het expliciet uitschrijf.

Deze dus:
C++:
1
2
3
4
5
6
7
template<typename T>
    MBED_DEPRECATED_SINCE("mbed-os-5.1",
        "The attach function does not support cv-qualifiers. Replaced by "
        "attach(callback(obj, method), type).")
    void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) {
        attach(callback(obj, method), type);
    }


Dit soort dingen is allemaal wat makkelijker te begrijpen als je je basiskennis C++ wat opschroeft trouwens ;)

[ Voor 5% gewijzigd door farlane op 04-05-2017 16:51 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • jctjepkema
  • Registratie: Mei 2011
  • Laatst online: 04-10 15:47
expor schreef op donderdag 4 mei 2017 @ 15:08:
Dat ligt eraan vanaf waar je de functie wil binden. In geval de oplossing die ik gaf (en die je zelf ook had gevonden) doe je dit vanuit de class die the handler implementeert, vandaar 'this'. De oplossing van farlane is vanuit main gezien. Dan maak je dus eerst het object aan, en bind je vanaf daar een member functie van dat object. Het eerste argument van attach() is in dat geval dus een pointer naar het object dat de handler implementeert.

Edit: Ik zie nu pas waar je naar refereerde met die callback, dat is niet per see nodig voor zover ik het zie in de API. Het derde argument, RxIrq is overigens default al gezet en is dus optioneel.
Ik heb zo over jou bericht heen gelezen 8)7 excuses, ik vind jou manier echter wel iets mooier, omdat ik dan de main.cpp wat leger hou. en ik de functies later kan plaatsen in een programma zonder al te veel moeite.
farlane schreef op donderdag 4 mei 2017 @ 16:50:
[...]


De callback klasse en this hebben niets met elkaar te maken, maar met combinatie van parameters die je gebruikt ( this en de pointer-naar-memberfunctie ) kan een callback object worden gemaakt.

Dat wordt in jouw geval gedaan door een functie van de SerialBase class, die hetzelfde doet als ik. Die functie is gemarkeerd als deprecated, vandaar dat ik het expliciet uitschrijf.

Deze dus:
C++:
1
2
3
4
5
6
7
template<typename T>
    MBED_DEPRECATED_SINCE("mbed-os-5.1",
        "The attach function does not support cv-qualifiers. Replaced by "
        "attach(callback(obj, method), type).")
    void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) {
        attach(callback(obj, method), type);
    }


Dit soort dingen is allemaal wat makkelijker te begrijpen als je je basiskennis C++ wat opschroeft trouwens ;)
hartstikke bedankt! Ja klopt zeker op de opleiding krijgen wij echt maar een minimale hoeveelheid C++, wat we krijgen heb ik ruim voldoende gehaald, maar ik wil er nu wel wat dieper op in gaan. In mijn optiek en mijn vanuit mijn docent's oogpunt krijgen wij te weinig C++ voor een opleiding Elektrotechniek, maar ja het analoge deel van de opleiding hoort er ook nog bij.

ik krijg op de manier die expor voorstelde een warning:

Warning: Function "mbed::SerialBase::attach(T *, void (T::*)(), mbed::SerialBase::IrqType) [with T=readFunction]" (declared at <a href="#" onmousedown="mbed_doc_goto('/LBL_LED_DRVR_V2R01//extras/mbed_97feb9bacc10/drivers/SerialBase.h', '117'); return false;">/extras/mbed_97feb9bacc10/drivers/SerialBase.h:117</a>) was declared "deprecated" in "functions.cpp", Line: 9, Col: 13

Beetje zoeken kom ik hier op uit:
https://developer.mbed.or...thod-mbedInterruptInfall/

Ik ga mij eens inlezen op die callback en dat dan maar gebruiken

Acties:
  • 0 Henk 'm!

  • expor
  • Registratie: Juni 2005
  • Laatst online: 01-10 22:53
Ja was dus een deprecated oplossing, excuus :) Dan moet je dat wrappen in de callback die farlane aangaf en dan werkt het weer gewoon ;)

C++:
1
serial.attach(Callback(this, &readFunction::read));

[ Voor 21% gewijzigd door expor op 04-05-2017 18:09 ]

AMD 5800X3D | 16gb DDR 4 @ 3800/14 | 4070 Ti | 1TB Samsung Evo 970, 1TB Samsung Evo 860, 512MB Crucial


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
jctjepkema schreef op donderdag 4 mei 2017 @ 17:43:
Ik heb zo over jou bericht heen gelezen 8)7 excuses, ik vind jou manier echter wel iets mooier, omdat ik dan de main.cpp wat leger hou. en ik de functies later kan plaatsen in een programma zonder al te veel moeite.
Het ligt er een beetje aan hoe hard je de ReadFunction class wilt koppelen aan het Serial object.

Als je de attach binnen in het ReadFunction object doet, koppel je het Serial object die de callback doet en get ReadFunction object waar het in staat "hard" aan elkaar. Als je dat doet, hoort de ReadFunction misschien ook wel de eigenaar te zijn van het Serial object. Als dat zo is, moet deze misschien ook wel geen ReadFunction heten. (Voor wat naslagwerk omtrent dit verschijnsel : Wikipedia: Loose coupling en haar broer Wikipedia: Cohesion (computer science) )

Dat soort overwegingen zijn een beetje de basis van een goed doordacht software design, maar ik ben me er van bewust dat dat op dit moment voor jou wat te ver gaat.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Gebaseerd op wat ik in zijn code lees is "ReadFunction" een class voor iets van een Projector object. Sowieso los van allerlei dingen can cohesies is een class een naam geven van [iets]Function een beetje apart :).

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Sissors schreef op vrijdag 5 mei 2017 @ 09:10:
Gebaseerd op wat ik in zijn code lees is "ReadFunction" een class voor iets van een Projector object. Sowieso los van allerlei dingen can cohesies is een class een naam geven van [iets]Function een beetje apart :).
Wat is een Projector object?

[edit]
@Sissors Haha, dacht dat je aan een design pattern refereerde die ik gemist had, maar nu snap ik het weer :D

[ Voor 14% gewijzigd door farlane op 05-05-2017 12:04 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Hetgeen wat hij maakt:
code:
1
readFunction projector(PA_9, PA_10, PA_8);/*Tx, Rx, NPN transistor*/


Mijn gok is/was dat dit de aansturing van iets van een fysieke projector is.

Acties:
  • 0 Henk 'm!

  • jctjepkema
  • Registratie: Mei 2011
  • Laatst online: 04-10 15:47
Sissors schreef op vrijdag 5 mei 2017 @ 10:51:
Hetgeen wat hij maakt:
code:
1
readFunction projector(PA_9, PA_10, PA_8);/*Tx, Rx, NPN transistor*/


Mijn gok is/was dat dit de aansturing van iets van een fysieke projector is.
Klopt inderdaad is intern in een projector waar ik mee knutsel.
Pagina: 1