Skip to content
Snippets Groups Projects
Commit 4d7336b5 authored by Lennard Karger's avatar Lennard Karger
Browse files

Testprojekte für neue Libraryversionen angelegt

parent c17c96d7
No related branches found
No related tags found
2 merge requests!4PIO Projekte in main-Branch implementieren,!3Vorbereitung Main merge PIO - Projektstrukturen
Showing
with 1750 additions and 5 deletions
......@@ -205,10 +205,6 @@ void BlePoll::setPollAddress(int chnIn, int adrIn, int areaIn, bool masterIn, bo
nak = nakIn;
}
bcPduPtr BlePoll::getPduAdress(){
return &pduOut;
}
void BlePoll::setPduAddress()
{
setPduAddress(&pduOut);
......
#ifndef SoaapBleSlave_h
#define SoaapBleSlave_h
#include "LoopCheck.h"
#include "StateMachine.h"
#include "nRF52840Radio.h"
#include "BlePoll.h"
#include "ComRingBuf.h"
#include "nRF52840Ser.h"
#include "SoaapMsg.h"
#include "Monitor.h"
#include "nRF52840Twi.h"
#include "SensorLSM9DS1.h"
#include "nRF52840Gpio.h"
//#define SlaveACM1
bool sendData(PlpType plpType, byte *dest);
......
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
// ----------------------------------------------------------------------------
// SoaapBleMaster.ino
// Beispielhafte Anwendung SOAAP / Steuerung optischer und akustischer Ausgaben
// Kommunikation über BLE-Funkanäle mit Bewerbungstelegrammen
// P o l l i n g - M a s t e r
// ----------------------------------------------------------------------------
// Editor: Robert Patzke
// URI/URL: www.hs-hannover.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 1. November 2021
// Letzte Bearbeitung: 4. Februar 2022
//
#include "Arduino.h"
#include "SoaapBleMaster.h"
// ----------------------------------------------------------------------------
LoopCheck lc;
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse LoopCheck
// Darüber wird das Zeitverhalten gesteuert (Software-Timer) und geprüft
// ----------------------------------------------------------------------------
nRF52840Radio bleCom;
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse nRF52840Radio
// Darüber wird direkt die CPU (nRF52840) auf dem Arduino-Board zum Senden und
// Empfangen von BLE-Beacons angesprochen.
#define bleCycleTime 250
// ----------------------------------------------------------------------------
BlePoll blePoll((IntrfRadio *) &bleCom, micros);
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse BlePoll
// Darüber werden das Polling des Masters als auch die Antworten der Slaves
// gesteuert. Es können Geräte entwickelt werden, die nur Master oder Slave
// sind und solche mit Doppelfunktion, wenn kein expliziter Master
// eingesetzt und das Netzwerk über Spontan-Master quasi dezentral
// betrieben werden soll.
// ----- Parameter ------------------------------------------------------------
// <&bleCom> Die Klasse (vom angenommenen Typ IntrfRadio), die die Daten-
// übertragung abwickelt. Hier wird eine Instanz von nRF52840Radio
// angebunden. Für andere Hardware kann eine entsprechende Klasse
// verwendet werden, die von IntrfRadio abgeleitet wurde.
// <micros> Eine Funktion, die die verstrichene Zeit in Mikrosekunden gibt.
// Damit werden Zeiten (z.B. Time-Out) berechnet.
// Wird hier der Wert NULL übergeben, dann werden die Zeiten aus
// dem Aufrufzyklus (bleCycleTime) in Mikrosekunden berechnet,
// was hier einer Auflösung von 250 Mikrosekunden entspricht.
#define NrOfSlavesToPoll 5
// Die Anzahl der Slaves, die der Master aufrufen soll (Polling).
// Es wird grundsätzlich mit der Adresse 1 begonnen und nach dem Aufruf die
// Adresse inkrementiert, also immer die Slaves Adr = 1 bis
// Adr = NrOfSlavesToPoll+1 aufgerufen.
// ACHTUNG!
// Diese Zahl muss kleiner/gleich der in BlePoll.h definierten maximalen
// Anzahl der Slaves (MAXSLAVE) sein, weil die Ressourcen darüber statisch
// festgelegt werden.
SerParams ttyParams;
// ----------------------------------------------------------------------------
nRF52840Ser tty;
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse nRF52840Ser (UART)
// Darüber werden die seriellen Schnittstellen (UARTE0 und UARTE1) des
// nRF52840 bedient.
// Die Parameter werden in einer Struktur <SerParams> über die Funktion
// <begin(...)> gesetzt.
#define sndBufSize 256
byte sndBuffer[sndBufSize];
// ----------------------------------------------------------------------------
ComRingBuf crb;
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse <ComRingBuf>
// Damit wird ein Ringpuffer aufgebaut, der eine serielle Schnittstelle bedient.
// Der Speicher muss extra eingerichtet und mit der Funktion
// <setWriteBuffer(sndBufSize, sndBuffer)> übergeben werden.
// Die Klasse für die serielle Schnittstelle muss von <IntrfSerial> abgeleitet
// sein, die Instanz wird mit der Funktion <begin(...)> übergeben.
#define appCycleTime 500
StateMachine ap(apInit, NULL, appCycleTime);
// Eine statische Instanz für die Zustandsmaschine, die hier für die
// Anwendung (App) von SOAAP eingesetzt wird
// ----- Parameter ------------------------------------------------------------
// <smInit> Der zuerst aufgerufene Zustand (Funktion). Weitere Zustände
// werden in den weiteren Zustandsfunktionen eingesetzt.
// <NULL> Hier kann eine weitere Zustandsfunktion angegeben werden,
// die dann grundsätzlich vor dem Verzweigen in einen Zustand
// aufgerufen wird.
// <smCycleTime> Die Zukluszeit (Takt) der Zustandsmaschine in Mikrosekunden
// ----------------------------------------------------------------------------
SoaapMsg sMsg;
// ----------------------------------------------------------------------------
// Eine statische Instanz der Klasse <SoaapMsg>
// Damit werden SOAAP-spezifische Meldungen/Telegramme generiert und ausgewertet
// und SOAAP-spezifische Datentypen und Parameter definiert.
#ifdef DebugTerminal
// ----------------------------------------------------------------------------
// Zum Debuggen und weitere Analysen der Programmumgebung und Funktionstests
// Es ist ein (richtiges) Terminal erforderlich, mit dem einzelnen Zeichen
// direkt abgeschickt und die eintreffenden direkt angezeigt werden.
// ----------------------------------------------------------------------------
#define smCycleTime 5
StateMachine sm(smInit, NULL, smCycleTime);
// Eine statische Instanz für die Zustandsmaschine, die hier für allgemeine
// Steuerungen, Überwachungen und zum Debugging verwendet wird
// ----- Parameter ------------------------------------------------------------
// <smInit> Der zuerst aufgerufene Zustand (Funktion). Weitere Zustände
// werden in den weiteren Zustandsfunktionen eingesetzt.
// <NULL> Hier kann eine weitere Zustandsfunktion angegeben werden,
// die dann grundsätzlich vor dem Verzweigen in einen Zustand
// aufgerufen wird.
// <smCycleTime> Die Zukluszeit (Takt) der Zustandsmaschine in Millisekunden
Monitor mon(modeEcho | modeNl,0,&lc);
// Eine statische Instanz (mit Konstruktordaten) der Klasse Monitor
// Darüber wird mit (direkten) Terminals (z.B. VT100) kommuniziert
// Unter Linux werden hier GtkTerm (siehe Internet) und
// ArduinoMonTerm (eigene Entwicklung mit grafischen Wertanzeigen) eingesetzt.
// Das in den IDEs integrierte Terminal ist dafür meistens nicht geeigent,
// weil damit keine direkte Kommunikation (getipptes Zeichen sofort gesendet)
// möglich ist.
// ----- Parameter ------------------------------------------------------------
// <mode Echo> Alle eintreffenden Zeichen werden sofort zurückgesendet
// <mode NL> Vor der Ausgabe des Prompt (M>) erfolgt CR/LF
// <0> Für Speicherzugriffe wird von 32 Bit ARM ausgegangen
// <&lc> Für Zeitüberwachungen und entsprechende statisctische Daten
// greift die Monitor-Klasse auf die LoopCheck-Klasse zu
// ----------------------------------------------------------------------------
#endif
// ============================================================================
void setup()
// ============================================================================
{
bleCom.begin(); // Initialisierung der Datenübertragung
//bleCom.setPower(0x08); // Maximale Sendeleistung bei nRF52840
// TEST
bleCom.setPower(0x0FC); // Reduzierte Sendeleistung beim Schreibtisch-Test
blePoll.begin(BlePoll::ctMASTER, NrOfSlavesToPoll, BlePoll::atDevSOAAP, 10000);
// Initialisierung des Polling mit folgenden Parametern:
// <BlePoll::ctMASTER> Es wird ein Master eingerichtet
// <NrOfSlavesToPoll> Anzahl gepollter Slaves (s.o.)
// <BlePoll::atSOAAP> Spezielle Anwendung SOAAP
// <10000> INT-Watchdog-Timeout beim Lesen in Mikrosekunden
blePoll.setEmptyPollParams(2000, 500, 2000);
// Setzen der Parameter für das leere Polling zur Feststellung der
// vorhandenen Slaves und Aufbau einer Poll-Liste für den Datenaustausch
// ----- Parameter ----------------------------------------------------------
// <2000> Anzahl der Poll-Durchläufe, solange kein Slave gefunden wird
// <500> Anzahl weiterer Durchläufe, nachdem wenigstens ein Slave gefunden ist
// <2000> Time-Out (Zeit für Slave zum Antworten) in Mikrosekunden
for(int i = 1; i <= NrOfSlavesToPoll; i++)
blePoll.setDataPollParams(i, 1, 10, 1000);
// Setzen der Parameter beim Datenpolling, für Slaves individuell
// ----- Parameter ----------------------------------------------------------
// <i> Adresse des Slave (1-..)
// <1> Priorität beim Aufruf, 0 = immer bis max 65535 = sehr selten
// <10> minimale Priorität bei automatischer Prioritätsreduzierung
// im Fall von Störungen (Time-Out)
// <1000> Time-Out (Zeit für Slave zum Antworten) in Mikrosekunden
#ifdef DebugTerminal
blePoll.stopEP(); // Das Polling muss extra gestartet werden
#endif
// Initialisierung von serieller Schnittstelle und Ringpuffer
// --------------------------------------------------------------------------
ttyParams.inst = 0; // Instanzindex der Schnittstelle (0,1)
ttyParams.rxdPort = 1; // Nummer des IO-Port mit RxD-Pin
ttyParams.rxdPin = 10; // Nummer des RxD-Pin am Port
ttyParams.txdPort = 1; // Nummer des IO-Port mit TxD-Pin
ttyParams.txdPin = 3; // Nummer des TxD-Pin am Port
ttyParams.speed = Baud115200; // Enumerator für Bitrate
ttyParams.type = stStd; // Spannungsausgang
tty.begin(&ttyParams, (IntrfBuf *) &crb);
// Übergeben von Parametern und Referenz auf Ringpufferverwaltung
// für die Übergabe empfangener Zeichen
tty.startSend(); // Sendebetrieb aktivieren
crb.setWriteBuffer(sndBufSize, sndBuffer);
// Speicher an Ringpufferverwaltung übergeben
crb.begin((IntrfSerial *) &tty);
// Referenz auf Schnittstelle an Ringpufferverwaltung
// für die Übergabe zu sendender Zeichen
}
// ============================================================================
void loop()
// ============================================================================
{
lc.begin(); // Muss am Anfang von LOOP aufgerufen werden
// --------------------------------------------------------------------------
#ifdef DebugTerminal
mon.run(); // Der Monitor bekommt bei jedem Durchlauf die CPU
#endif
// Alle 250 Mikrosekunden erfolgt der Aufruf des Ble-Polling
//
if(lc.timerMicro(lcTimer0, bleCycleTime, 0))
blePoll.run();
// ----- Parameter der Software-Timer ---------------------------------------
// <lcTimer0> Id/Nummer des Timer, zur Zeit werden bis 10 Timer unterstützt
// lcTimer0 bis lcTimer9 (einstellbar in LoopCheck.h)
// <bleCycleTime> Ablaufzeit in Einheit des Timer-Typ (Micro/Milli)
// hier in Mikrosekunden (timerMicro)
// <0> Anzahl der Wiederholungen, 0 = unbegrenzt
// Alle 500 Mikrosekunden erfolgt der Aufruf der Anwendung
//
if(lc.timerMicro(lcTimer1, appCycleTime, 0, 10000))
ap.run();
#ifdef DebugTerminal
// Jede Sekunde erfolgt die Ausgabe einer Versionsmeldung
// das kann über c0 am Terminal abgeschaltet werden
//
if(lc.timerMilli(lcTimer2, 1000, 0))
{
if(!mon.cFlag[0])
mon.printcr((char *)"%@TestBleMaster (ttyACM0), Version 20220303");
smWaitPolling();
}
// Die Zeichen %@ am Anfang steuern die Ausgabe bei AndroidMonTerm in ein
// Textfeld (Label) statt auf das Terminal-Display
// Alle 5 Millisekunden erfolgt der Aufruf der Zustandsmaschine
//
if(lc.timerMilli(lcTimer3, smCycleTime, 0))
{
sm.run();
}
#endif
// --------------------------------------------------------------------------
lc.end(); // Muss vor dem Ende von LOOP aufgerufen werden
}
// ****************************************************************************
// Z u s t a n d s m a s c h i n e S O A A P - A n w e n d u n g (ap)
// ****************************************************************************
//
byte apTmpByteArray[256]; // Zwischenspeicher für Zeichenfolgen
int apNrOfMeasBytes; // Anzahl der empfangenen Messwertbytes
byte apMeasByteArray[32]; // Zwischenspeicher für Messwerte
byte apSlaveList[NrOfSlavesToPoll]; // Merker für gepollte Slaves
int apNrOfSlaves; // Aktuelle Anzahl von Slaves
int curListIdx; // Aktueller Index für Slaveliste
int area; // Area des aktuellen Slave
int sMsgLen; // Länge einer SOAAP-Meldung
int slNr; // Slave-Nummer (Adresse)
int txNr; // Anzahl versendeter Zeichen
SoaapApId sAppId; // Anwendungs-Id aus Sicht SOAAP
PlpType pAppId; // Anwendungs-Id aus Polling-Sicht
#ifdef TEST001
char testMsgBuf[256];
#endif
// ----------------------------------------------------------------------------
// Initialisierungen
//
void apInit()
{
#ifdef TEST001
crb.putLine("Initialisierung");
#endif
// Eventuelle Initialisierung
ap.enter(apWaitDE); // in nächsten Zustand schalten
}
// ----------------------------------------------------------------------------
// Warten, bis Datenaustausch Master/Slave erfolgt
//
void apWaitDE()
{
if(!blePoll.DataExchange)
return; // Verbleiben in diesem Zustand bis Leerpolling beendet
apNrOfSlaves = blePoll.getSlaveList(apSlaveList, NrOfSlavesToPoll);
// Ermitteln der angeschlossenen Slaves
#ifdef TEST001
crb.putStr("Slaveliste\r\n");
#endif
ap.enter(apWaitMeas);
}
// ----------------------------------------------------------------------------
// Warten auf neuen Messwert von einem Slave
//
void apWaitMeas()
{
// Ermitteln, ob einer der Slaves einen Messwert hat
//
for(curListIdx = 0; curListIdx < apNrOfSlaves; curListIdx++)
{
slNr = apSlaveList[curListIdx];
if(blePoll.measAvail(slNr)) break;
}
if(curListIdx == apNrOfSlaves) return;
// Wenn kein Slave neue Messwerte hat,
// dann im nächsten Zustandstakt Abfrage wiederholen
#ifdef TEST001
crb.putStr("Messwerte\r\n");
#endif
// Slave (curListIdx) hat Messwerte übermittelt
// diese werden mit dem nächsten Takt verarbeitet
ap.enter(apProcMeas);
}
// ----------------------------------------------------------------------------
// Verarbeiten der Daten vom Slave
//
void apProcMeas()
{
#ifdef TEST001
if(ap.firstEnter())
{
slNr = apSlaveList[curListIdx];
sprintf(testMsgBuf,"Slave-Nr = %d\r\n",slNr);
crb.putStr(testMsgBuf);
}
//ap.enter(apWaitMeas);
//return;
#endif
// Parameter und Daten für die SOAAP-Meldung holen
//
slNr = apSlaveList[curListIdx];
area = blePoll.getArea(slNr);
pAppId = blePoll.getAppId(slNr);
apNrOfMeasBytes = blePoll.getMeas(slNr, apMeasByteArray);
#ifdef TEST001
ap.enter(apWaitMeas);
return;
#endif
// Abbildung des Polling-Telegramm-Typs auf die SOAAP-Anwendungs-Id
//
switch(pAppId)
{
case plptMeas9:
sAppId = saiDefaultMeas;
break;
case plptMeas13:
sAppId = saiMaximalMeas;
break;
case plptMeas9Ctrl4:
sAppId = saiDefaultMeasCtrl;
break;
default:
sAppId = saiDefaultMeas;
break;
}
// Konstruktion der SOAAP-Meldung
//
sMsgLen = sMsg.getMsgA(area, slNr, sAppId, (char *) apTmpByteArray, apMeasByteArray);
// Senden des Telegramm über serielle Schnittstelle
//
txNr = crb.putStr((char *) apTmpByteArray);
// Auf nächsten Messwert von einem Slave warten
//
ap.enter(apWaitMeas);
}
#ifdef DebugTerminal
// ****************************************************************************
// Z u s t a n d s m a s c h i n e z u m D e b u g g e n (sm)
// ****************************************************************************
//
dword debDword;
byte tmpByteArray[256];
void smInit()
{
sm.enter(smCheckJobs);
}
// ----------------------------------------------------------------------------
// Abfrage der Monitorschalter
// ----------------------------------------------------------------------------
//
void smCheckJobs()
{
if(mon.cFlag[1] && !mon.busy)
sm.enter(smDebDword);
else if(mon.cFlag[2] && !mon.busy)
sm.enter(smCtrlPolling);
else if(mon.cFlag[3] && !mon.busy)
sm.enter(smReadPollValues);
else if(mon.cFlag[4] && !mon.busy)
sm.enter(smCheckSer);
}
// ----------------------------------------------------------------------------
// Debug-Informationen
// ----------------------------------------------------------------------------
//
void smDebDword()
{
int idx;
if(sm.firstEnter())
{
mon.print((char *) "DebDword[");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
if(mon.lastKeyIn >= 0x30 && mon.lastKeyIn <= 0x39)
{
idx = mon.lastKeyIn & 0x0F;
mon.print(idx);
mon.print((char *) "]=");
debDword = blePoll.debGetDword(idx);
mon.println(debDword);
sm.resetEnter();
}
else
{
if(mon.lastKeyIn == ' ')
{
mon.cFlag[1] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
}
}
// ----------------------------------------------------------------------------
// Steuern des Polling-Prozesses
// ----------------------------------------------------------------------------
//
TxStatistics txStatistics;
void smCtrlPolling()
{
dword tmpDw;
short tmpShort;
int i;
PlpMeas6Ptr resPtr;
if(sm.firstEnter())
{
mon.print((char *) "polling ");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
// --------------------------------------------------------------------------
if(mon.lastKeyIn == 'P' || mon.lastKeyIn == 'p')
{
if(blePoll.stoppedEP())
{
blePoll.resumeEP();
mon.println((char *) "fortgesetzt");
sm.resetEnter();
}
else
{
blePoll.stopEP();
sm.enter(smWaitPolling);
}
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'C' || mon.lastKeyIn == 'c')
{
blePoll.resetPollCounters();
mon.println((char *) "Zähler zurückgesetzt");
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'R' || mon.lastKeyIn == 'r')
{
mon.print((char *) "Radiopuffer = ");
bleCom.getPduMem(tmpByteArray, 0, 10);
mon.println(tmpByteArray, 10, ' ');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'S' || mon.lastKeyIn == 's')
{
mon.print((char *) "Sendepuffer = ");
bleCom.getPduSent(tmpByteArray, 0, 10);
mon.println(tmpByteArray, 10, ' ');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'L' || mon.lastKeyIn == 'l')
{
mon.print((char *) "Slave-Liste: ");
int nrOfSlaves = blePoll.getSlaveList(tmpByteArray, 255);
mon.println(tmpByteArray, nrOfSlaves, ',');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'T' || mon.lastKeyIn == 't')
{
mon.print((char *) "TxStat [");
dword bleStat = blePoll.getStatistics(&txStatistics);
mon.print(bleStat);
mon.print((char *) "] ");
mon.print(txStatistics.mode); mon.cprint(' ');
mon.print(txStatistics.interrupts); mon.cprint(' ');
mon.print(txStatistics.recs); mon.cprint(' ');
mon.print(txStatistics.sendings); mon.cprint(' ');
mon.print(txStatistics.aliens); mon.cprint(' ');
mon.print(txStatistics.wrongs); mon.cprint(' ');
mon.print(txStatistics.pollAcks); mon.cprint(' ');
mon.print(txStatistics.pollNaks); mon.cprint(' ');
mon.print(txStatistics.crcErrors); mon.print(" s[ ");
mon.print(txStatistics.memDumpSnd,8,' '); mon.print("] r[ ");
mon.print(txStatistics.memDumpRec,16,' '); mon.cprintln(']');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn >= '0' && mon.lastKeyIn <= '9')
{
int idx = mon.lastKeyIn & 0x0F;
SlavePtr slPtr = blePoll.getSlavePtr(idx);
PollStatePtr pPtr = blePoll.getPollPtr(slPtr->pIdx);
mon.print((char *) "Slave[");
mon.print(idx);
mon.print((char *) "] ");
mon.print(slPtr->cntTo); mon.cprint(' ');
mon.print(slPtr->cntNakEP); mon.cprint(' ');
mon.print(slPtr->cntAckDP); mon.cprint(' ');
if(slPtr->cntAckDP == 0)
{
if(slPtr->cntTo == 0)
tmpDw = slPtr->cntNakEP;
else
tmpDw = slPtr->cntNakEP / slPtr->cntTo;
}
else
{
if(slPtr->cntTo == 0)
tmpDw = slPtr->cntAckDP;
else
tmpDw = slPtr->cntAckDP / slPtr->cntTo;
}
mon.print(tmpDw); mon.cprint(' ');
resPtr = (PlpMeas6Ptr) &slPtr->result;
mon.print(slPtr->cntLostPdu); mon.cprint('|');
mon.print(slPtr->cntErrCrc); mon.cprint('|');
//mon.print(slPtr->result.measCnt); mon.cprint('|');
mon.print(resPtr->measCnt); mon.cprint('|');
mon.print(slPtr->cntLostMeas); mon.cprint(' ');
for(i = 0; i < 6; i++)
{
//tmpShort = (short) slPtr->result.meas[i];
tmpShort = (short) resPtr->meas[i];
mon.prints(tmpShort); mon.cprint(' ');
}
mon.print((char *) " Poll[");
mon.print(slPtr->pIdx);
mon.print((char *) "] ");
mon.print(pPtr->status); mon.cprint(' ');
mon.println(pPtr->slIdx);
sm.resetEnter();
}
else
{
if(mon.lastKeyIn == ' ')
{
mon.cFlag[2] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
}
}
void smWaitPolling()
{
if(!blePoll.stoppedEP()) return;
mon.println((char *) "angehalten");
sm.enter(smCtrlPolling);
}
// ----------------------------------------------------------------------------
// Testen der seriellen Schnittstelle
// ----------------------------------------------------------------------------
//
void smCheckSer()
{
if(sm.firstEnter())
{
mon.print((char *) "TestSer...");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
if(mon.lastKeyIn == ' ')
{
mon.cFlag[4] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
else
{
crb.putChr(mon.lastKeyIn);
mon.cprint(mon.lastKeyIn);
mon.lastKeyIn = ':';
}
}
// ----------------------------------------------------------------------------
// Debug-Informationen
// ----------------------------------------------------------------------------
//
void smReadPollValues()
{
}
#endif // DebugTerminal
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
// ----------------------------------------------------------------------------
// SoaapBleSlave.ino
// Beispielhafte Anwendung SOAAP / Steuerung optischer und akustischer Ausgaben
// Kommunikation über BLE-Funkanäle mit Bewerbungstelegrammen
// P o l l i n g - S l a v e
// ----------------------------------------------------------------------------
// Editor: Robert Patzke
// URI/URL: www.mfp-portal.de
//-----------------------------------------------------------------------------
// Lizenz: CC-BY-SA (wikipedia: Creative Commons)
// Datum: 1. November 2021
// Letzte Bearbeitung: 1. November 2021
//
#include "Arduino.h"
#include "SoaapBleSlave.h"
#define SlaveADR1
#ifdef SlaveADR1
#define SlaveADR 1
#define StartMsg "%@TestBleSlave (Adr=1), Version 20220424 "
#endif
#ifdef SlaveADR4
#define SlaveADR 4
#define StartMsg "%@TestBleSlave (Adr=4), Version 20220424 "
#endif
LoopCheck lc;
// Eine statische Instanz der Klasse LoopCheck
// Darüber wird das Zeitverhalten gesteuert (Software-Timer) und geprüft
#ifdef DebugTerminal
Monitor mon(modeEcho | modeNl,0,&lc);
// Eine statische Instanz (mit Konstruktordaten) der Klasse Monitor
// Darüber wird mit (direkten) Terminals (z.B. VT100) kommuniziert
// Unter Linux werden hier GtkTerm (siehe Internet) und
// ArduinoMonTerm (eigene Entwicklung mit grafischen Wertanzeigen) eingesetzt.
// Das in den IDEs integrierte Terminal ist dafür meistens nicht geeignet,
// weil damit keine direkte Kommunikation (getipptes Zeichen sofort gesendet)
// möglich ist.
// ----- Parameter ------------------------------------------------------------
// <mode Echo> Alle eintreffenden Zeichen werden sofort zurückgesendet
// <mode NL> Vor der Ausgabe des Prompt (M>) erfolgt CR/LF
// <0> Für Speicherzugriffe wird von 32 Bit ARM ausgegangen
// <&lc> Für Zeitüberwachungen und entsprechende statisctische Daten
// greift die Monitor-Klasse auf die LoopCheck-Klasse zu
#endif
nRF52840Radio bleCom;
// Eine statische Instanz der Klasse nRF52840Radio
// Darüber wird direkt die CPU (nRF52840) auf dem Arduino-Board zum Senden und
// Empfangen von BLE-Beacons angesprochen.
#define bleCycle 250
BlePoll blePoll((IntrfRadio *) &bleCom, micros);
// Eine statische Instanz der Klasse BlePoll
// Darüber werden das Polling des Masters als auch die Antworten der Slaves
// gesteuert. Es können Geräte entwickelt werden, die nur Master oder Slave
// sind und solche mit Doppelfunktion, wenn kein expliziter Master
// eingesetzt und das Netzwerk über Spontan-Master quasi dezentral
// betrieben werden soll.
// ----- Parameter ------------------------------------------------------------
// <&bleCom> Die Klasse (vom angenommenen Typ IntrfRadio), die die Daten-
// übertragung abwickelt. Hier wird eine Instanz von nRF52840Radio
// angebunden. Für andere Hardware kann eine entsprechende Klasse
// verwendet werden, die von IntrfRadio abgeleitet wurde.
// <micros> Eine Funktion, die die verstrichene Zeit in Mikrosekunden gibt.
// Damit werden Zeiten (z.B. Time-Out) berechnet.
// Wird hier der Wert NULL übergeben, dann werden die Zeiten aus
// dem Aufrufzyklus (bleCycleTime) in Mikrosekunden berechnet,
// was hier einer Auflösung von 500 Mikrosekunden entspricht.
#ifdef DebugTerminal
#define smCycleTime 5
void smInit(); // Vorwärtsreferenz auf die weiter unten definierte Funktion
StateMachine sm(smInit, NULL, smCycleTime);
// Eine statische Instanz für die Zustandsmaschine, die hier für allgemeine
// Steuerungen, Überwachungen und zum Debugging verwendet wird
// ----- Parameter ------------------------------------------------------------
// <smInit> Der zuerst aufgerufene Zustand (Funktion). Weitere Zustände
// werden in den weiteren Zustandsfunktionen eingesetzt.
// <NULL> Hier kann eine weitere Zustandsfunktion angegeben werden,
// die dann grundsätzlich vor dem Verzweigen in einen Zustand
// aufgerufen wird.
// <smCycleTime> Die Zukluszeit (Takt) der Zustandsmaschine in Millisekunden
#endif
nRF52840Twi twi;
// Eine statische Instanz der Klasse nRF52840Twi
// Darüber wird direkt die CPU (nRF52840) auf dem Arduino-Board zum Senden und
// Empfangen von I2C (TWI) Botschaften aufgerufen.
#define SensorCycle 500
SensorLSM9DS1 sens((IntrfTw *) &twi, SensorCycle);
// Eine statische Instanz der Klasse SensorLSM9DS1 zum Zugriff
// auf den Sensor LSM9DS1 über den I2C-Bus (TWI)
// ----- Parameter ------------------------------------------------------------
// <&twi> Die Klasse (vom angenommenen Typ IntrfTw), die die Datenüber-
// tragung auf I2C abwickelt. Hier wird eine Instanz von nRF52840Twi
// angebunden. Für andere Hardware kann eine entsprechende Klasse
// verwendet werden, die von IntrfTw abgeleitet wurde.
//
// <SensorCycle> Der Zugriff auf den Sensor erfolgt mit einer Zustands-
// maschine, deren Takt über die Periodenzeit SensorCycle
// in Mikrosekunden definiert ist. Siehe dazu entsprechenden
// Timeraufruf in LOOP.
nRF52840Gpio gpio;
// Zugriff auf die Anschlüsse des Board
bool getValues(PlpType plpType, byte *dest);
// Vorwärtsreferenz für Datenübergabe
bool xchgCtrl(PlpType plpType, byte *dest, byte *src, int sSize);
// Vorwärtsreferenz für Steuerungsaustausch
void setup()
{
TwiParams twiPar; // Parameter für den I2C-Bus
gpio.configArd(ArdA0A3, IfDrvInput | IfDrvPullUp);
#ifdef DebugTerminal
mon.config(6); // 6 Anzeigekanäle, die von ArduinoMonTerm aufgebaut werden
for(int i = 0; i < 6; i++)
{
if(i < 3)
mon.config(i+1,'C',16000,-16000,NULL); // Kanalnummer, Typ, Maxwert, Minwert
else
mon.config(i+1,'C',4000,-4000,NULL);
}
#endif
bleCom.begin(); // Initialisierung der Datenübertragung
//bleCom.setPower(0x008); // Maximale Sendeleistung bei nRF52840
bleCom.setPower(0x0FC); // Reduzierte Sendeleistung beim Schreibtisch-Test
blePoll.begin(BlePoll::ctSLAVE, SlaveADR, BlePoll::atSOAAP, 10000);
// Initialisierung des Polling mit folgenden Parametern:
// <BlePoll::ctSLAVE> Es wird ein Slave eingerichtet
// <SlaveADR> Adresse (Nummer) des Slave
// <BlePoll::atSOAAP> Spezielle Anwendung SOAAP
// <10000> INT-Watchdog-Timeout in Mikrosekunden
blePoll.setCbDataPtr(getValues);
blePoll.setCbCtrlPtr(xchgCtrl);
// Callbacks für Datenübergabe setzen
//blePoll.stopSR();
// Kein Empfangsbetrieb
// Spezifische Parameter für den I2C-Bus am Arduino Nano 33 BLE
//
twiPar.inst = 0; // 1. Instanz der I2C
twiPar.type = TwiMaster; // Auswahl Master/slave
twiPar.clkPort = 0; // Takt über Port 0 (P0)
twiPar.clkPin = 15; // Takt an Pin 15 (P0.15)
twiPar.dataPort = 0; // Daten über Port 0 (P0)
twiPar.dataPin = 14; // Daten an Pin 14 (P0.14)
twiPar.speed = Twi100k; // Taktfrequenz
twi.begin(&twiPar); // Initialisierung des I2C-Bus
sens.begin(FreqAG119, 12, MaxAcc4g, MaxGyro2000dps, FreqM20, 10, MaxMag16G);
// Initialisierung der Sensorabfrage mit folgenden Parametern
//
// <FreqAG119> Beschleunigungssensoren und Gyroskop mit 119 Hz abgefragt
//
// <12> Vor der Wertübergabe wird der Mittelwert über 12 Messungen
// gebildet. Die Messfrequenz beträgt daher ca. 10 Hz.
//
// <MaxAcc4g> Der Maximalausschlag der Beschleunigung ist 4g
//
// <MaxGyro2000dps> Maximalausschlag des Gyro ist 2000 Grad/s
//
// <FreqM40> Der Magnetfeldsensor wird mit 20 Hz abgetastet
//
// <8> Mittelwertbildung über 10 Messwerte, also 2 Hz
//
// <MaxMag16G> Der Maximalwert entspricht 16 Gauss
sens.syncValuesAG();
sens.syncValuesM();
// Rücksetzen des Ready-Bit für Messwertübergabe
}
#ifdef DebugTerminal
char runView[4] = {'|','/','-','\\'};
int runViewIdx = 0;
#endif
void loop()
{
lc.begin();
// --------------------------------------------------------------------------
#ifdef DebugTerminal
// Der Monitor wird ständig aufgerufen und stellt damit eine grundsätzliche
// Belastung dar. Das ist für die Entwicklung auch vorgesehen.
// Es entsteht dadurch eine Reserve für den produktiven Einsatz.
//
mon.run();
#endif
// Alle 500 Mikrosekunden erfolgt der Aufruf des Ble-Polling
//
if(lc.timerMicro(lcTimer0, bleCycle, 0))
blePoll.run();
// ----- Parameter der Software-Timer ---------------------------------------
// <lcTimer0> Id/Nummer des Timer, zur Zeit werden bis 10 Timer unterstützt
// lcTimer0 bis lcTimer9 (einstellbar in LoopCheck.h)
// <bleCycleTime> Ablaufzeit in Einheit des Timer-Typ (Micro/Milli)
// hier in Mikrosekunden (timerMicro)
// <0> Anzahl der Wiederholungen, 0 = unbegrenzt
// Alle 500 Mikrosekunden erfolgt der Aufruf der Sensorzustandsmaschine
//
if(lc.timerMicro(lcTimer1, SensorCycle, 0))
sens.run();
#ifdef DebugTerminal
// Alle 5 Millisekunden wird die Zustandsmaschine für
// betriebliche Abläufe aufgerufen
//
if(lc.timerMilli(lcTimer2, smCycleTime, 0))
{
sm.run();
}
// Jede halbe Sekunde erfolgt die Ausgabe der Version
//
if(lc.timerMilli(lcTimer3, 500, 0))
{
if(!mon.cFlag[0])
{
mon.print((char *) StartMsg);
mon.cprintcr(runView[runViewIdx]);
runViewIdx++;
if(runViewIdx > 3) runViewIdx = 0;
}
}
#endif
// --------------------------------------------------------------------------
lc.end();
}
// ----------------------------------------------------------------------------
// Übergabe der Daten an die BLE-Kommunikation
// ----------------------------------------------------------------------------
//
RawDataAG rawDataAG;
RawDataM rawDataM;
bool getValues(PlpType plpType, byte *dest)
{
bool newData;
int si,di;
memset(rawDataAG.byteArray,0,12);
newData = sens.getValuesAG(&rawDataAG);
si = di = 0;
if(newData)
{
switch(plpType)
{
case plptMeas6:
for(si = 0; si < 12; si++)
dest[di++] = rawDataAG.byteArray[si];
break;
case plptMeas9Ctrl4:
sens.getValuesM(&rawDataM);
for(si = 0; si < 12; si++)
dest[di++] = rawDataAG.byteArray[si];
for(si = 0; si < 6; si++)
dest[di++] = rawDataM.byteArray[si];
break;
}
}
return(newData);
}
int procSize;
byte procData[32];
byte procPath;
byte procCnt;
bool xchgCtrl(PlpType plpType, byte *dest, byte *src, int sSize)
{
int si,di;
bool retv;
si = di = 0;
retv = false;
switch(plpType)
{
case plptMeas9Ctrl4:
for(si = 0; si < sSize; si++)
procData[si] = src[si];
procSize = sSize;
dest[di++] = procPath;
dest[di++] = procCnt;
dest[di++] = (byte) (gpio.readArd(ArdA0A3) & 0x0F);
dest[di++] = 0;
retv = true;
break;
}
return(retv);
}
#ifdef DebugTerminal
// ****************************************************************************
// Z u s t a n d s m a s c h i n e
// ****************************************************************************
//
dword debDword;
byte tmpByteArray[256];
CalValueAG calData;
CalValue calValue;
void smInit()
{
sm.enter(smCheckJobs);
}
// ----------------------------------------------------------------------------
// Abfrage der Monitorschalter
// ----------------------------------------------------------------------------
//
void smCheckJobs()
{
if(mon.cFlag[1] && !mon.busy)
sm.enter(smDebDword);
else if(mon.cFlag[2] && !mon.busy)
sm.enter(smCtrlPolling);
else if(mon.cFlag[3] && !mon.busy)
sm.enter(smCheckSens);
/*
else if(mon.cFlag[4] && !mon.busy)
sm.enter(smCheckSens);
*/
}
// ----------------------------------------------------------------------------
// Debug-Informationen
// ----------------------------------------------------------------------------
//
void smDebDword()
{
int idx;
if(sm.firstEnter())
{
mon.print((char *) "DebDword[");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
if(mon.lastKeyIn >= 0x30 && mon.lastKeyIn <= 0x39)
{
idx = mon.lastKeyIn & 0x0F;
mon.print(idx);
mon.print((char *) "]=");
debDword = blePoll.debGetDword(idx);
mon.println(debDword);
sm.resetEnter();
}
else
{
if(mon.lastKeyIn == ' ')
{
mon.cFlag[1] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
}
}
// ----------------------------------------------------------------------------
// Steuern des Polling-Prozesses
// ----------------------------------------------------------------------------
// Es ist sowohl die Master- als auch die Slave-Funktion vorgesehen
//
TxStatistics txStatistics;
void smCtrlPolling()
{
if(sm.firstEnter())
{
mon.print((char *) "polling ");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
// --------------------------------------------------------------------------
if(mon.lastKeyIn == 'P' || mon.lastKeyIn == 'p')
{
if(blePoll.stoppedEP())
{
blePoll.resumeEP();
mon.println((char *) "fortgesetzt");
sm.resetEnter();
}
else
{
blePoll.stopEP();
sm.enter(smWaitPolling);
}
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'S' || mon.lastKeyIn == 's')
{
mon.print((char *) "Sendepuffer = ");
bleCom.getPduSent(tmpByteArray, 0, 10);
mon.println(tmpByteArray, 10, ' ');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'R' || mon.lastKeyIn == 'r')
{
mon.print((char *) "Radiopuffer = ");
bleCom.getPduMem(tmpByteArray, 0, 10);
mon.println(tmpByteArray, 10, ' ');
sm.resetEnter();
}
// --------------------------------------------------------------------------
else if(mon.lastKeyIn == 'T' || mon.lastKeyIn == 't')
{
mon.print((char *) "TxStat [");
dword bleStat = blePoll.getStatistics(&txStatistics);
mon.print(bleStat);
mon.print((char *) "] ");
mon.print(txStatistics.mode); mon.cprint(' ');
mon.print(txStatistics.interrupts); mon.cprint(' ');
mon.print(txStatistics.recs); mon.cprint(' ');
mon.print(txStatistics.sendings); mon.cprint(' ');
mon.print(txStatistics.aliens); mon.cprint(' ');
mon.print(txStatistics.wrongs); mon.cprint(' ');
mon.print(txStatistics.pollAcks); mon.cprint(' ');
mon.print(txStatistics.pollNaks); mon.cprint(' ');
mon.print(txStatistics.crcErrors); mon.print(" r[ ");
mon.print(txStatistics.memDumpRec,8,' '); mon.print("] s[ ");
mon.print(txStatistics.memDumpSnd,16,' '); mon.cprintln(']');
sm.resetEnter();
}
else
{
if(mon.lastKeyIn == ' ')
{
mon.cFlag[2] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
}
}
void smWaitPolling()
{
if(!blePoll.stoppedEP()) return;
mon.println((char *) "angehalten");
sm.enter(smCtrlPolling);
}
// ----------------------------------------------------------------------------
// (4) Testen der Sensorzugriffe
// ----------------------------------------------------------------------------
//
char charOut[2];
void smCheckSens()
{
if(sm.firstEnter())
{
mon.print((char *) "Sensorzugriff ");
mon.lastKeyIn = ':';
}
if(mon.lastKeyIn == ':') return;
charOut[0] = mon.lastKeyIn;
charOut[1] = '\0';
mon.println(charOut);
if(mon.lastKeyIn == '0' || mon.lastKeyIn == ' ')
{
mon.cFlag[3] = false;
mon.print((char *) "-- Schleifenabbruch - drücke Enter");
sm.enter(smCheckJobs);
}
else if(mon.lastKeyIn == '1')
sm.enter(smSensReset1);
else if(mon.lastKeyIn == '2')
sm.enter(smSensReset2);
else if(mon.lastKeyIn == '3')
sm.enter(smSensGetValues1);
else if(mon.lastKeyIn == '4')
sm.enter(smSensGetValues2);
else if(mon.lastKeyIn == '5')
sm.enter(smSensGetValues3);
else if(mon.lastKeyIn == '6')
sm.enter(smSensGetValues4);
else if(mon.lastKeyIn == '7')
sm.enter(smSensGetValues5);
else if(mon.lastKeyIn == '8')
sm.enter(smSensGetValues6);
else if(mon.lastKeyIn == 'c')
sm.enter(smSensDebugValues);
else if(mon.lastKeyIn == 'e')
sm.enter(smSensGetErrors);
else if(mon.lastKeyIn == 'r')
sm.enter(smSensGetRunCounts);
else if(mon.lastKeyIn == 's')
sm.enter(smSensGetSoaapValues);
else if(mon.lastKeyIn == 't')
sm.enter(smSensGetTimeOuts);
else
sm.resetEnter();
mon.lastKeyIn = ':';
}
void smSensReset1()
{
int retv = sens.resetAG();
//int retv = twi.writeByteReg(0x6B, 0x22, 0x05);
mon.print((char *) "resetAG = ");
mon.println(retv);
sm.enter(smCheckSens);
}
void smSensReset2()
{
int retv = sens.resetM();
//int retv = twi.writeByteReg(0x1E, 0x21, 0x0C);
mon.print((char *) "resetM = ");
mon.println(retv);
sm.enter(smCheckSens);
}
void smSensGetValues1()
{
if(sm.firstEnter())
sens.syncValuesAG();
if(!sens.getValuesAG(&rawDataAG)) return;
mon.print((char *) "ValueA = ");
mon.print(rawDataAG.valueAG.A.x);
mon.print((char *) " ");
mon.print(rawDataAG.valueAG.A.y);
mon.print((char *) " ");
mon.println(rawDataAG.valueAG.A.z);
sm.enter(smCheckSens);
}
char outValue[64];
void smSensGetValues2()
{
if(sm.firstEnter())
sens.syncValuesAG();
if(!sens.getValuesAG(&calData)) return;
mon.print((char *) "ValueA = ");
sprintf(outValue,"%f ",calData.A.x);
mon.print(outValue);
sprintf(outValue,"%f ",calData.A.y);
mon.print(outValue);
sprintf(outValue,"%f ",calData.A.z);
mon.println(outValue);
sm.enter(smCheckSens);
}
void smSensGetValues3()
{
if(sm.firstEnter())
{
sens.syncValuesAG();
mon.lastKeyIn = ':';
}
if(!sens.getValuesAG(&calData)) return;
mon.print((char *) "Values A = ");
sprintf(outValue,"%+5.3f ",calData.A.x);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.y);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.z);
mon.println(outValue);
if(mon.lastKeyIn == ' ')
sm.enter(smCheckSens);
}
void smSensGetValues4()
{
if(sm.firstEnter())
{
sens.syncValuesAG();
mon.lastKeyIn = ':';
}
if(!sens.getValuesAG(&calData)) return;
mon.print((char *) "Values AG = ");
sprintf(outValue,"%+5.3f ",calData.A.x);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.y);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.z);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.x);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.y);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.z);
mon.println(outValue);
if(mon.lastKeyIn == ' ')
sm.enter(smCheckSens);
}
void smSensGetValues5()
{
if(sm.firstEnter())
{
sens.syncValuesAG();
mon.lastKeyIn = ':';
sm.setTimeOut(1000);
}
if(sm.timeOut())
{
mon.println((char *) " Time Out");
sm.enter(smCheckSens);
return;
}
if(!sens.getValuesAG(&calData)) return;
sm.setTimeOut(1000);
mon.print((char *) "Values AGM = ");
sprintf(outValue,"%+5.3f ",calData.A.x);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.y);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calData.A.z);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.x);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.y);
mon.print(outValue);
sprintf(outValue,"%+5.1f ",calData.G.z);
mon.print(outValue);
sens.getValuesM(&calValue);
sprintf(outValue,"%+5.3f ",calValue.x);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calValue.y);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calValue.z);
mon.println(outValue);
if(mon.lastKeyIn == ' ')
sm.enter(smCheckSens);
}
void smSensGetValues6()
{
if(sm.firstEnter())
{
sens.syncValuesAG();
mon.lastKeyIn = ':';
sm.setTimeOut(1000);
}
if(sm.timeOut())
{
mon.println((char *) " Time Out");
sm.enter(smCheckSens);
return;
}
if(!sens.getValuesAG(&rawDataAG)) return;
sm.setTimeOut(1000);
mon.print((char *) "Values AGM = ");
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.A.x);
mon.print(outValue);
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.A.y);
mon.print(outValue);
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.A.z);
mon.print(outValue);
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.G.x);
mon.print(outValue);
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.G.y);
mon.print(outValue);
sprintf(outValue,"%4X ",(unsigned short) rawDataAG.valueAG.G.z);
mon.println(outValue);
/*
sens.getValuesM(&calValue);
sprintf(outValue,"%+5.3f ",calValue.x);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calValue.y);
mon.print(outValue);
sprintf(outValue,"%+5.3f ",calValue.z);
mon.println(outValue);
*/
if(mon.lastKeyIn == ' ')
sm.enter(smCheckSens);
}
void smSensGetValues7()
{
if(sm.firstEnter())
{
sens.syncValuesAG();
mon.lastKeyIn = ':';
sm.setTimeOut(1000);
}
if(sm.timeOut())
{
mon.println((char *) " Time Out");
sm.enter(smCheckSens);
return;
}
if(!sens.getValuesAG(&rawDataAG)) return;
sm.setTimeOut(1000);
mon.print((char *) "%~Values AGM = $");
sprintf(outValue,"#@%04X$",(unsigned short) rawDataAG.valueAG.A.x);
mon.print(outValue);
sprintf(outValue,"#A%04X$",(unsigned short) rawDataAG.valueAG.A.y);
mon.print(outValue);
sprintf(outValue,"#B%04X$",(unsigned short) rawDataAG.valueAG.A.z);
mon.print(outValue);
sprintf(outValue,"#C%04X$",(unsigned short) rawDataAG.valueAG.G.x);
mon.print(outValue);
sprintf(outValue,"#D%04X$",(unsigned short) rawDataAG.valueAG.G.y);
mon.print(outValue);
sprintf(outValue,"#E%04X$",(unsigned short) rawDataAG.valueAG.G.z);
mon.print(outValue);
if(mon.lastKeyIn == ' ')
sm.enter(smCheckSens);
}
void smSensGetSoaapValues()
{
sm.enter(smSensGetValues7);
}
void smSensDebugValues()
{
mon.print((char *) "Werte: toValueStatusAG=");
mon.print(sens.debGetDword(1));
mon.print((char *) " toValueStatusM=");
mon.println(sens.debGetDword(2));
sm.enter(smCheckSens);
}
void smSensGetErrors()
{
mon.print((char *) "Errors AG: AdrNak=");
mon.print(sens.errorCntAdrNakAG);
mon.print((char *) " DataNak=");
mon.print(sens.errorCntDataNakAG);
mon.print((char *) " Overrun=");
mon.print(sens.errorCntOverAG);
mon.print((char *) " M: AdrNak=");
mon.print(sens.errorCntAdrNakM);
mon.print((char *) " DataNak=");
mon.print(sens.errorCntDataNakM);
mon.print((char *) " Overrun=");
mon.println(sens.errorCntOverM);
sm.enter(smCheckSens);
}
void smSensGetTimeOuts()
{
mon.print((char *) "TimeOuts AG: TwiStat=");
mon.print(sens.toCntTwiStatusAG);
mon.print((char *) " TwiData=");
mon.print(sens.toCntTwiDataAG);
mon.print((char *) " Status=");
mon.print(sens.toCntStatusAG);
mon.print((char *) " M: TwiStat=");
mon.print(sens.toCntTwiStatusM);
mon.print((char *) " TwiData=");
mon.print(sens.toCntTwiDataM);
mon.print((char *) " Status=");
mon.println(sens.toCntStatusM);
sm.enter(smCheckSens);
}
void smSensGetRunCounts()
{
mon.print((char *) "RunCounts: ");
for(int i = 0; i < NrOfRunStates; i++)
{
mon.print((char *) " ");
mon.print(sens.runStateCntArray[i]);
}
mon.print((char *) " Total=");
mon.println(sens.runStateCntTotal);
sm.enter(smCheckSens);
}
#endif // DebugTerminal
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment