Pages: [1] 2   Go Down
Author Topic: Projektvorstellung: simpleThreads auf dem Arduino mit Hilfe von Makros  (Read 4660 times)
0 Members and 1 Guest are viewing this topic.
Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Last Update 18.11.2013

Oft ist es so, dass große Programme irgendwann unübersichtlich werden. Ab diesen Punkt hilft einem nur noch Abstraktion des Codes und eine Zerlegung auf mehrere Dateien (Tabs oder Libs). Um diesem Prozess zu vereinfachen habe ich eine Lib geschrieben die Threads generiert. Jeder Thread kann zeitbasiert (timebased) oder eventbasiert (eventbased) angelegt werden. Bei den zeitbasierten Threads wird nochmal zwischen Threads mit statischer und dynamischer Ausführzeit unterschieden. Bei den dynamischen Threads kann die Zeit zur Laufzeit des Programmes noch verändert werden. Wenn mehrer Threads angelegt sind, müssen diese nicht mehr einzeln in der Loop Funktion aufgerufen werden. Dazu gibt es eine Run-Funktion (simpleThread_run()) die automatisch, entweder der Reihenfolge nach oder Priorität orientiert die einzelnen Threads aufruft.

Verwendungsmöglichkeiten dieser Lib:
  • strukturierter Programmablauf von mehreren Unterprogrammen
  • Display aktualisieren (750ms), Buttons auslesen (50ms), Sensorwerte auslesen (500ms), Messerte per Ethernet übertragen (jede Minute)
  • Verschiedene Statusanzeigen die Zeitlich gesteuert auf einem LCD angezeigt werden sollen
  • Verschachtelte Zeitabläufe, z.B: bei der Fotografie (mehrere Bilder in bestimmten Zeitabfolgen), oder beim Aquarium Beleuchtung an/aus /Ströumungsrichtungen ...  
  • oder Andere Funktionen die zyklisch oder Zustands gesteuert ausgeführt werden


Mir ist bewusst das es schon eine ähnliche Lib gibt. Es mir sehr wichtig so wenig wie möglich an Ram zu belegen, daher befinden sich in der Klasse nur Makros. Durch die Makros wird der Quellcode für die Threads beim kompilieren generiert und im Flash-Speicher abgelegt. Je nach Thread Art wird unterschiedliche viel Ram fest belegt.

Allgemein gilt für das Thread Management
Für jeden Thread werden zwei Bit benötigt. In diesen wird gespeichert ob der Thread gestartet/gestoppt ist und ob der Therad zurückgesetzt werden soll. Für den ersten Thread der angelegt wird, werden zwei Byte reserviert. Jeder weitere Thread bis zum achten greift auf diese zwei Byte zurück. Erst der neunte Thread reserviert erneut zwei Byte.
1 - 8 => zwei Byte
9 - 16 => zwei weitere Byte ...
Diese Speicherbelegung trifft auf eventbasierte Threads zu.

zeitbasierter Thread mit statischer Zeit
Auf Basis der algemeinen Belegung, werden hier vier weitere Bytes im Ram belegt

zeitbasierter Thread mit dynamischer Zeit
Auf Basis der algemeinen Belegung, werden hier acht weitere Bytes im Ram belegt

Initialisierung von Threads:
Zuerst muss die simpleThread.h eingebunden werden. Anschließen muss außerhalb von allen existierenden Funktionen die Initialisierung eingeleitet werden. Bei dieser wird angegeben wie viel neue Threads angelegt werden sollen. Wenn der Wert über die Anzahl nicht der existierenden Thread Anzahl entspricht, treten Fehler auf, die sich dadurch außern, dass das Programm einfach durchläuft ohne start / stop / wait_time / events.
Nach dem festlegen der Thread Anzahl, werden die einzelnen Threads angelegt. Jeder Thread muss zuerst ein eindeutige ID bekommen, die von 0 an aufwärts gezählt werden muss.
Befehle:
  • simpleThread_init( anzahl an threads )
  • simpleThread_new_timebased_static(id, thread_name, wait_time)
  • simpleThread_new_timebased_dynamic(id, thread_name, wait_time)
  • simpleThread_new_eventbased(id, thread_name)

Anschließen wird die Priorität festgelegt. Hierzu werden die Thread namen in einer Liste eingetragen. Der oberste Eintrag hat die größte Priorität. Dies ist in den Beispielen am besten verdeutlicht.

Für jeden Therad der oben angelegt wurde, muss zudem eine Setup- und Loop-Funktion angelegt werden. Die Loop Funktion besitzt einen Rückgabe Wert, auf den weiter unten eingegangen wird. Dieser kann gesetzt werden, muss aber nicht.
Der erstellte Code könnte so aussehen:
Code:
void simpleThread_setup(thread_name)
  {  
  
  }  

  boolean simpleThread_loop(thread_name)
  {

  }

Aufbau eines Threads:
Jeder Thread besteht aus einer SETUP und LOOP Funktion. Die Setup Funktion wird einmal zu Beginn aufgerufen. Anschließend wird ausschließlich die Loop Funktion ausgeführt. Ein Thread kann gestartet und gestoppt werden. Mit dem Reset Befehl setzt man einen Thread zurück, sprich beim nächsten Aufruf wird die Setup-Funktion erneut aufgerufen. Jeder Thread kann mit  "isRun" überprüft werden, ob dieser gestartet oder gestoppt ist. Zudem gibt es die Möglichkeit
Befehle:
  • simpleThread_start(thread_name) oder simpleThread_event_start(thread_name)
  • simpleThread_stop(thread_name)
  • simpleThread_stopStable(thread_name)
  • simpleThread_reset(thread_name) oder simpleThread_event_reset
  • simpleThread_restart(therad_name) oder simpleThread_event_restart
  • simpleThread_loop(thread_name)
  • simpleThread_setup(thread_name)
  • simpleThread_stable(thread_name)
  • simpleThread_run(_simpleThread_M_without_priority  oder  _simpleThread_M_with_priority)

Den Programmablauf eines einzelnen Threads kann man sich wie folgt vorstellen:


Um Kontrollfunktionen bei vielen Threads zu vereinfachen, können Gruppen von Threads angelegt werden. Jede Gruppe kann einzeln gestartet, gestoppt, zurückgesetzt oder zurückgesetzt und gestartet werden.
Befehle:
  • simpleThread_group_init(group_name, anzahl der threads in der gruppe)
  • simpleThread_group(thread name)
  • simpleThread_group_start(groupe_name)
  • simpleThread_group_stop(group_name)
  • simpleThread_group_stopStable(group_name)
  • simpleThread_group_reset(group_name)
  • simpleThread_group_restart(group_name)

Zur Vereinfachung gibt es auch die Möglichkeit die Setup- oder Loop- Funktion eines Threats direkt aufzurufen. Dafür wurden folgende Befehle eingeführt:
  • simpleThread_call(thread_name)
  • simpleThread_call_loop(thread_name)
  • simpleThread_call_setup(thread_name)
  • simpleThread_call_stable(thread_name)


Da es Event- Zeitbasierte Threads gibt wird der Ablauf wie im folgenden Bild generiert. Der Thread der dort eingezeichnet ist, wurde vom Ablauf her weiter oben schon beschrieben.


Dieser Ablauf der nun Beschrieb wurde ist in den gesamten Ablauf eingebettet. Der gesamte Ablauf kann der Reihenfolge nach oder mittels einer Priorität durchlaufen werden.

der Reihenfolge nach (A):
Bei jedem Thread wird der Reihenfolge nach überprüft ob dieser gestartet wurde und ob bei zeitbasierten Threads die Wartezeit abgelaufen ist oder bei eventbasierten Threads das ein Event gestartet wurde. Wenn keine Bedingung erfüllt ist, wird der nächste Thread überprüft. Ansonsten wird der Thread ausgeführt.

mittels Priorität (B)
Es findet die gleiche Überprüfung wie schon unter "der Reihenfolge nach (A)" beschrieben statt. Der Unterschied liegt in der Überprüfung der Bedingungen. Wenn keine Bedingung erfüllt ist, passiert das gleich wie unter (A). Wenn der Thread ausgeführt wird, beginnt anschließend die Schleife von neuem. Je nach Rückgabewert der Thread-Loop-Funktion. Ist der Rückgabewerte "null" oder "false" startet die Schleife die die einzelnen Threads aufruft neu. Wenn der Wert "true" ist, beginnt die Prozedur von neuem.

Das System kann man so verstehen:


Im Anhang ist ein Archiv in dem sich die simpleThreads Lib befinden. Der Ordner muss nach dem Enpacken in das libraries Verzeichnis kopiert werden. Wenn die Arduino Software anschließend gestartet wird kann ein Beispiel unter Datei->Beispiele->Beispiele->simpleThread geöffnet werden. Im Moment werden 5 Beispiele mit angeboten. Ich werde die Beispiel in der nächsten Zeit noch sinnvoller gestalten. Im Moment zeigen diese nur, wie man die Funktionen anlegt.

Beispiel Code
Code:
#include <simpleThread.h>  
 
#define _sT_cnt         _sT_cnt_1

simpleThread_init(_sT_cnt ); //init one new thread
simpleThread_new_timebased_static  (_sT_P1  , _sT_millis, 1000    , _sT_start  , Loop_1);


void setup()
{  
  Serial.begin(9600);
  simpleThread_initSetup(_sT_cnt);
}

void loop()
{
  simpleThread_run(_sT_priority);;
}

//global var
uint8_t g_thread_counter = 0;

//new setup for loop_1
void simpleThread_setup(Loop_1)
{
}  
// new loop function for thread loop_1
boolean simpleThread_loop(Loop_1)
{  
  Serial.println(g_thread_counter); // output counter value every 1000 ms    
  g_thread_counter++; // increment counter    
  return false;    
}

Ich würde mich freuen wenn Ihr das Beispiel mal testen würdet und eure Meinung dazu abgebt.



* simpleThread.rar (17.26 KB - downloaded 53 times.)
« Last Edit: November 18, 2013, 11:48:53 am by Jomelo » Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

erstmal Daumen hoch für die geleistete Arbeit. Solche Projekte bringen meiner Meinung nach die arduino::std::Lib ein Stückchen weiter.

Mir sind zwei Punkte nicht ganz klar:
1. Wo siehst du den Vorteil von Makros? Wie du schon geschrieben hast, werden Sie zur Laufzeit an die Stellen kopiert wo sie aufgerufen werden.
D. h. es wird kein Speicher (weder SRAM noch Flash) eingespart.

2. Die 4 Byte+3 Bit pro Thread ist für mich nicht nachvollziehbar. Threadname: (uint8_t) 1 Byte,  Timer: (unsigned long) 4 Byte = 5 Byte pro Thread.
Dazu kommen noch etliche Rechnungen mit statischen Zahlen (7,1,0) und LOOP uint8_t. Aber das müssten 1-2 Byte (je nachdem wie viele gleichzeitig
benötigt werden, habs mir nicht zu genau angeschaut) unabhängig von der Anzahl der Threads sein.
Könntest du es vielleicht näher erläutern? Die 3 Bit interessieren mich besonders smiley

Ansonsten finde ich deinen Einsatz der Makros sehr kreativ. Mit drei functions viele Threadfunktionen abzubilden ist nicht ohne.

Interessant wäre auch die Auswertung ab wie viel Threads überhaupt sich lohnt so ein Konstrukt zu verwenden (Laufzeit, Speicherbedarf).
Denn für zwei Threads z. B. könnte ich mir schlankere Lösung vorstellen.

Grüße
Nighti
Logged

Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, das stimmt, die Berechnungen habe ich nicht mit eingerechnet und den Namen des Threads auch nicht. Wobei wie die Speicherauslastung beim Namen ist kann ich nicht genau sagen, da es ja nur ein Zeiger auf eine Funktion ist.  

In den 3 Bit des Threads wird gespeichert:  start/stop ,  reset,  first_init.

Die Variablen werden erstmal als uint8_t angelegt, also bei einem Thread werden 3 Byte belegt. Aber wenn 8 Threads verwendet werden sind es immer noch 3 Byte die den Status speichern. Erst ab dem 9 Thread müssen 6 Byte belegt werden. Daher werden "grob gesagt"  3 Bit pro Thread für das Management im Hintergrund benötigt. Vielleicht fällt mir noch eine bessere Variante ein um die Divisionen zu minimieren.

Der Vorteil von Makros ist, das ich den Quellcode den ich überall einfügen müsste durch verhältnismäßig einfache Aufrufe einheitlich darstellen kann. Zudem hat der Programmierer nicht mehr das Problem Änderungen an allen Stellen im Programm durchführen wenn es um eine Erweiterung geht. Ich bin mir nicht sicher ab wann ein Objekt das ich für jeden Thread erstellen könnte, kleiner wäre als der direkte Funktionsaufruf.

Zum Aufbau des Konstrukts:
Ich verwende dieses Konstrukt mit einem LCDMenu in dem ich für unterschiedliche Unterpunkte Threads starten und Stoppen kann, je nachdem wie ich diese gerade brauche. Bei größeren Projekten gefiel mir nicht, dass ich um eine Unterfunktion zu starten oder zu Stoppen immer gleich eine Variable(1 Byte) angelegt hatte. Zudem, wenn man ein Menü mit 30 Buttons für verschiedene Funktionen hat, kommt man schnell mit den Variabel Namen durcheinander und es wird unübersichtlich.

Für kleine Projekte lohnt sich das nur, wenn man die Möglichkeit zur Erweiterung für später offen halten möchte.  

Edit:
Es lässt mir ja so gerade keine Ruhe. Also ich habe nun nochmal versucht herauszubekommen, wie lange ein Leerer Thread benötigt um ausgeführt zu werden. Dafür habe ich mein Beispiel Umgeschrieben, so das 20 Threads ausgeführt werden.
Bei 20 Threads ist die Auszuführende Zeit  <1 ms.

Flash-Speicher:
- Einbindung der Thread Struktur für einen Thread: 364 Byte
- Einbindung für jeden weiteren Thread: 106 Byte
« Last Edit: May 09, 2013, 06:23:53 pm by Jomelo » Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry für die schlaflose Nacht, aber als Student bist es ja gewohnt  smiley-wink

Das mit den 3 Bits ist nun klarer, danke. Um schnell Bits auslesen zu können ist immer noch Shiften die bessere Wahl.
Könntest auch direkt die Funktionen  bitWrite(), bitSet(), bitClear() verwenden. Oder Makros daraus erstellen smiley

Quote
Bei größeren Projekten gefiel mir nicht, dass ich um eine Unterfunktion zu starten oder zu Stoppen immer gleich eine Variable(1 Byte) angelegt hatte..

Ja, das meinte ich mit der Skalierung. Bei 2,3,4 Threads ist der Verwaltungsaufwand in Bits zu speichern nicht angemessen,
aber bei 20,30,40 Threads sieht die Sache schon ganz anders aus. Wenn du dafür eine Grafik erstellen könntest, dann
kriegst du potenziell mehr Anhänger der Lib.
Logged

Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich habe ein Update des ersten Threads durchgeführt. Die Datei die im Anhang ist, wurde ebenfalls überarbeitet.

Änderungen:
- die simpleTools Lib wird nicht mehr benötigt
- die Threads werden nur noch durch Macros und bestehende Arduino Funktionen generiert
- Vorhandene Divisionen wurden bis auf die Initialisierung entfernt
- Die Thread Funktionen sehen nun wieder wie Funktionen aus (mit Geschweiften Klammern)
- Es gibt für das Thread_Setup und die Thread_Loop Schleife zwei getrennte Funktionen, so wie es für ein Arduino Programm üblich ist
- Threads können mit dynamischen Zeiten erstellt werden
- Intern: Umstellung auf bitWrite und bitRead


Die Dokumentation einschließlich Grafiken werde ich mal erstellen, wenn ich mir sicher bin das die größten Fehler behoben sind.
« Last Edit: May 10, 2013, 07:04:31 am by Jomelo » Logged

Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ein letztes Update:

- Initialisierung weiter vereinfacht (_L_id, _H_id, und Zeit Definitionen entfernt)
- Divisionen wieder eingefügt, da hierdurch die Initialisierung von einem neuem Thread vereinfacht wird.
  Die Divisionen werden vom Compiler berechnet und als Konstante Zahl in die generierten Funktionen eingesetzt.
- Beispiel ins Englische übersetzt
- "default loop time" Definition mit in die Erstellung des Threads integriert.
Logged

Lost in Singapore
Offline Offline
Jr. Member
**
Karma: 4
Posts: 74
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry für die schlaflose Nacht, aber als Student bist es ja gewohnt  smiley-wink

Das mit den 3 Bits ist nun klarer, danke. Um schnell Bits auslesen zu können ist immer noch Shiften die bessere Wahl.
Könntest auch direkt die Funktionen  bitWrite(), bitSet(), bitClear() verwenden. Oder Makros daraus erstellen smiley



Kannst du mir bitte mal sagen wo und man das getestet wurde? Ich würde sogar sagen das das bitshiften auf einem AVR deutlich langsamer sein kann, als ein Vergleich mit einer Maske. Den je Shift wird ein Takt gebraucht!
Außerdem hab ich mir dazu auch mal das Listing angeschaut und der Compiler baut das gerne mal zu einem Vergleich um! Vermutlich eben weils schneller ist.
Logged


Germany
Offline Offline
Faraday Member
**
Karma: 59
Posts: 3072
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1<<7   ist natürlich eine Konstante, die der Compiler gleich aussrechnet, schlau wie er ist.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi k4ktus,

hab keine Laufzeittests gemacht wenn du das meinst. Ich kenne es aus der Softwareentwicklung für x86 Chips
und wenn der Compiler dieses Konstrukt erkennt und für Atmega richtig optimiert, dann umso besser.
Falls du Vergleichsbeispiele in C->Assembler hast, könntest sie gerne posten. Denke bin nicht der einzige
der gerne dazu lernt smiley

Grüße
Nighti
Logged

Lost in Singapore
Offline Offline
Jr. Member
**
Karma: 4
Posts: 74
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

1<<7   ist natürlich eine Konstante, die der Compiler gleich aussrechnet, schlau wie er ist.

Das weiß ich. Mir ging es um die Aussage: Shiften ist eh viel schneller. Und das ist, sorry, bullshit auf einem AVR. Würde der Compiler nicht optimieren würde die Zuweisung eins und zwei mindestens 8 Zyklen brauchen. 

Quote
eins = 1 << 7;
0000036D  LDI R24,0x80      Load immediate
0000036E  STD Y+3,R24      Store indirect with displacement
zwei = bitSet(zwei,7);
0000036F  LDD R24,Y+2      Load indirect with displacement
00000370  ORI R24,0x80      Logical OR with immediate
00000371  STD Y+2,R24      Store indirect with displacement
00000372  STD Y+2,R24      Store indirect with displacement
drei |= B10000000;
00000373  LDD R24,Y+1      Load indirect with displacement
00000374  ORI R24,0x80      Logical OR with immediate
00000375  STD Y+1,R24      Store indirect with displacement
Logged


Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Update 01.06.2013

  • neue Funktionen zur Lib hinzugefügt
    • simpleThread_new_timebased_static   legt einen Thread an der Zeitbasiert arbeitet und eine feste Zeit besitzt
    • simpleThread_new_timebased_dynamic legt einen Thread an der Zeitbasiert arbeitet und eine dynamische Zeit besitzt
    • simpleThread_new_eventbased  legt einen Thread an, der nur gestartet wird, wenn ein Event ausgelöst wurde
    • simpleThread_stopStable   ruft eine Funktion auf, mit der der Thread in einem stabilen Zustand gestoppt wird
    • simpleThread_all_start 
    • simpleThread_all_stop
    • simpleThread_all_reset
    • simpleThread_all_restart
    • simpleThread_group_init  Threads können in Gruppen definiert werden
    • simpleThread_group fügt einer Gruppe ein Element hinzu
    • simpleThread_group_start
    • simpleThread_group_stop
    • simpleThread_group_stopStable
    • simpleThread_group_reset
    • simpleThread_group_restart
    • simpleThread_dynamic_setLoopTime  verändert bei einem timebased_dynamic Thread die gesetzte Zeit
    • simpleThread_dynamic_getLoppTime  ließt die Zeit aus
    • simpleThread_dynamic_setDefaultTime  setzt die Zeit auf die als Default definierte Zeit zurück
    • simpleThread_dynamic_restartTimer startet den Zähler neu
    • simpleThread_dynamic_timeToZero   führt den Thread sofot aus
    • simpleThread_signal_init  hier werden signale definiert jedes signal ist 1 bit groß, für die erste 8 signale wird 1 byte belegt
    • simpleThread_signal  definiert ein signal mit id und namen
    • simpleThread_signal_set
    • simpleThread_signal_get
    • simpleThread_signal_reset
    • simpleThread_call  hier kann direkt ein Thread aufgerufen werden
    • simpleThread_call_setup ruft das Setup direkt auf
    • simpleThread_call_loop ruft die Loop Funktion direkt auf
    • simpleThread_call_stable ruft die Funktion die bei stopStable aufgerufen wird, direkt auf


  • Funktionsbezeichnungen Einheitlich umbenannt
  • Beispiele überarbeitet
  • Speicherplatz und Ram Belegung weiter minimiert
  • Initialisierung deutlich vereinfacht, gegenüber der ersten Lib Version
  • Dokumentation überarbeitet und mit Grafiken ergänzt, so dass der Ablauf verdeutlicht wird (hoffentlich)

So, erstmal viel erledigt ;-)
Rechtschreibfehler und Unschlüssigkeiten werde ich in den nächsten Tagen Stück für Stück abarbeiten.
Logged

Cloppenburg
Offline Offline
Edison Member
*
Karma: 30
Posts: 1395
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Werden eigentlich auch ältere Versionen angeboten? Habe gestern mal diese Lib getestet, verbraucht 2kb mehr als die ältere.
Logged

Nicht Mensch, nicht Tier: Programmierer halt...

Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
ich habe die älteren Versionen nicht mehr auf dem Rechner, da in diesen immer noch kleine Fehler enthalten waren. Bisher hatte ich in meinen Projekten nie ein Problem damit, das zuviel Speicher belegt wird.

Wie viele Threads verwendest du ?

[edit]
Die jetzige Version verbraucht etwas mehr Flash Speicher, da die Initialisierung der Threads vereinfacht wurde. Das es soviel mehr ist, kann ich mir kaum vorstellen.
[/edit]
« Last Edit: July 31, 2013, 07:24:01 am by Jomelo » Logged

Cloppenburg
Offline Offline
Edison Member
*
Karma: 30
Posts: 1395
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

mit der alten Lib 17.212 und der neuen 19.168

Code:
/* *********************************** */
/* Thread_init_and_get_temp 
/* *********************************** */
/* thread setup */
  void simpleThread_setup(Thread_init_and_get_temp)
  {       
  }
/* thread loop */
  boolean simpleThread_loop(Thread_init_and_get_temp)
  {
    if ( !ds.search(addr))
    {
      // No more Dallas chips present:
      ds.reset_search();           
      return false;
    }

    // Check for family code which is not DS18B20:
    if ( addr[0] != 0x28) {
      return false;
    }

    // The DallasTemperature library can do all this work for you!
    ds.reset();
    ds.select(addr);
    ds.write(0x44,0);          // start conversion, with parasite power off
   
 
    // Check whether chip is present:
    present = ds.reset();
    ds.select(addr);   
    ds.write(0xBE);             // Read Scratchpad
    for ( dsread = 0; dsread < 9; dsread++)
    {   // we need 9 bytes of data
      data[dsread] = ds.read();
    }
 
    Temp =  ((data[1] << 8) + data[0] ) * 0.0625;  // 12Bit = 0,0625 C per Bit

    //Überprüfen ob die minimale Temperatur überschritten ist
    if (Temp < temp_min)
    {
      simpleThread_start(Thread_check_temp_warning);
    }
    //Überprüfen ob die maximale Temperatur überschritten ist
    else if (Temp > temp_max)
    {
      simpleThread_start(Thread_check_temp_warning);
    }
    else
    {
      simpleThread_stop(Thread_check_temp_warning);
      digitalWrite(alarm, HIGH);
     
    }
    if (Temp < temp1)
    {
      digitalWrite(heizung, HIGH);

    }
    else if (Temp > temp1)
    {
      digitalWrite(heizung, LOW);

    }
}
 
 
 
/* *********************************** */
/* Thread_check_temp_warning 
/* *********************************** */
/* thread setup */
  //status variable
  boolean alarm_status = 0;
 
  void simpleThread_setup(Thread_check_temp_warning)
  {
    alarm_status = 0;   
  }
/* thread loop */
  boolean simpleThread_loop(Thread_check_temp_warning)
  {
    //signal invertieren, von 0->1 und umgekehrt, jedesmal wenn der Thread aufgerufen wird
    alarm_status = !alarm_status;
    digitalWrite(alarm, alarm_status);   
  }
 

   
/* *********************************** */
/* Thread_wendung
/* *********************************** */

  void simpleThread_setup(Thread_wendung)
  {   
    g_thread_counter = 0; 
  }

  boolean simpleThread_loop(Thread_wendung)
  { 
      g_thread_counter++;
    if(g_thread_counter > wendung) {
  digitalWrite(motorpin1,LOW);
  digitalWrite(motorpin2,HIGH);
    if(LCDML.Timer(g_timer_wait, wendung_dauer))
    { 
      digitalWrite(motorpin1,LOW);
      digitalWrite(motorpin2,LOW);
    }
     }
      // Counter zurücksetzen
    g_thread_counter = 0;
    simpleThread_restart(Thread_wendung);
  }

Code:
/* init thread system */
  simpleThread_init( 3 );   
/* create a new static thread, the id (max 255) must incremented */
  simpleThread_new_timebased_static (0, Thread_init_and_get_temp, 750);
  simpleThread_new_timebased_static (1, Thread_check_temp_warning, 1000);
  simpleThread_new_timebased_static (2, Thread_wendung, 60000); // 10800000=3Std, 7200000=2Std, 3600000=1Std
/* this table contains the function pointer, all threads must be registered here */
/* it is possible to define the priority here */
  FuncPtr g_simpleThread_priority[] =
  {
    simpleThread(Thread_init_and_get_temp),
    simpleThread(Thread_check_temp_warning),
    simpleThread(Thread_wendung)
  };
Logged

Nicht Mensch, nicht Tier: Programmierer halt...

Germany, Osnabrück
Offline Offline
God Member
*****
Karma: 30
Posts: 659
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Der Code entspricht nun noch der alten Version deines Projektes ?

Also bei mir belegen 5 Threads mit festen Zeiten (simpleThread_new_timebased_static)  nur gerade mal 908 Bytes im Flash speicher. Hier müsste ich um auf die 2 KB zu kommen erstmal wesentlich mehr Threads anlegen.

Schick mir mal per PM oder hier im Forum deinen Code der Initialisierung mit der neusten Lib Version.
Logged

Pages: [1] 2   Go Up
Jump to: