Teensyduino 1.54 Beta #12

Status
Not open for further replies.

Paul

Administrator
Staff member
Here is an twelfth beta test for Teensyduino 1.54.

This beta is meant as a 1.54 release candidate.


Linux 32 bit:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.linux32

Linux 64 bit:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.linux64

Linux ARM:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.linuxarm

Linux ARM64:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.linuxaarch64

MacOS 10.10 to 11.4:
https://www.pjrc.com/teensy/td_154-beta12/Teensyduino_MacOS_Catalina.zip

MacOS 10.8 to 10.14:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.dmg

Windows:
https://www.pjrc.com/teensy/td_154-beta12/TeensyduinoInstall.exe


Changes since Teensyduino 1.54-beta11:

Update NativeEthernet
Add cmsis_gcc.h, for Arduino_TensorFlowLite library
Fix Serial2 vs Serial4 on MicroMod (KurtE)
Add SD library SdFat_Usage example
Reduce CrashReport memory usage
_VectorsRam change to volatile
 
Win 10 install TD 1.54b12on IDE 1.8.15
-> deleted hardware/teensy/avr to be sure it was clear of changed/orphaned files

> No Block or Warn on Download or install
> Working for compiles of LittleFS

@Paul - is there a NULL CrashReport class for non_T_4.x/MM - to avoid build complaints?
 
For LittleFS Integrity Tests here are the No Edit No #ifdef versions for RAM and PSRAM :: Defragster/LittleFS/tree/main/examples/Integrity

There are 977 lines in the FUNCTIONS.ino that are common helper func()'s. I did some minimal output adjustment and found a bug giving printf a 64 bit size but not a %llu.
Code:
:: /12_dir/X_file.txt   Verify /12_dir/X_file.txt 13800B  @KB/sec 2447.24 ----DEL---- -- X
:: /12_dir/Y_file.txt   Verify /12_dir/Y_file.txt 14312B  @KB/sec 2447.33 ----DEL---- -- Y
:: /12_dir/Z_file.txt   Verify /12_dir/Z_file.txt 14824B  @KB/sec 2492.27 ----DEL---- -- Z
:: /12_dir/A_file.txt   Verify /12_dir/A_file.txt 7144B  @KB/sec 2375.79 ----DEL---- -- A
:: /12_dir/B_file.txt  +++ size 0: Add 2536 @KB/sec 61.86 	  Verify /12_dir/B_file.txt 2536B  @KB/sec 1819.23
:: /12_dir/C_file.txt  +++ size 0: Add 3048 @KB/sec 73.97 	  Verify /12_dir/C_file.txt 3048B  @KB/sec 1880.32
:: /12_dir/D_file.txt  +++ size 0: Add 3560 @KB/sec 85.21 	  Verify /12_dir/D_file.txt 3560B  @KB/sec 2045.98
:: /12_dir/E_file.txt  +++ size 0: Add 4072 @KB/sec 97.42 	  Verify /12_dir/E_file.txt 4072B  @KB/sec 2070.16

The MEDIA specific ready to run code for RAM.ino and PSRAM.ino (opps it has 16MB at this time) should run on any system
> Not sure if twin INO's is good to reduce what the user sees for quick testing? It seemed better for editing the variations versus the common functions.ino

Some chatty comments added on the header - feedback or help welcome ...

SPI and QSPI and MRAM will follow in the next 12 hrs ...
 
Just installed over beta11 on IDE 1.8.15 with no issues, warnings or other blocking messages from windows or Norton. Again installed on Win10x64 Home Edition

Ran @defragsters old LFSIntegrity sketch and verified that RAM disk does still work and retains the files on warm restart.

Also, ran the newest SDCARD_Usuage sketch and works flawlessly - only tested with BUILTIN_SDCARD. Any yes for the BUILTIN_SDCARD only FIFO or DMA works :)
 
Morning all again.
I started putting together a readme for LittleFS, https://github.com/mjs513/LittleFS/tree/main, just started so not much there. So if you all have any suggestions let me know.

That's a very clearly written readme. I like it a lot.

You asked for suggestions, so here two remarks:
  • If you put a c++ after the three opening back ticks of a code section, gitHub will nicely color code it.
  • Right before the QSPI section an example showing how to "access or create files in the same manner as you would with an SD Card using the SD Library bundled with Teensyduio." might be helpful for those not so familiar with the SD card interface.
 
That's a very clearly written readme. I like it a lot.

You asked for suggestions, so here two remarks:
  • If you put a c++ after the three opening back ticks of a code section, gitHub will nicely color code it.
  • Right before the QSPI section an example showing how to "access or create files in the same manner as you would with an SD Card using the SD Library bundled with Teensyduio." might be helpful for those not so familiar with the SD card interface.

@luni - thanks for your suggestions. Will do, as soon as I give my aching fingers a rest :)
 
@defragster
Thanks. Figured it would help with your examples as well.

Think I have add a few more notes in though on printing details for directory, memory usage and formatting. Need a break though :)
 
@defragster
Thanks. Figured it would help with your examples as well.

Think I have add a few more notes in though on printing details for directory, memory usage and formatting. Need a break though :)

Yes, it should after I get the 'mechancal' edits made for the Media types.

Found my mounted SPI chips : PSRAM, FLASH ( plus PJRC board ) , MRAM. But I had a hand wired female plug socket to the ProtoSupplies SPI breakouts that were 'repurposed' - I need to find/replace to test any SPI. ... Found it on a T_4 on PJRC Purple Display board ... code dated : "LFSintegrity.ino Dec 15 2020"

<EDIT> : NEW MRAMSPI sketch ran and found 7 month old data intact - and worked to extend - Need to drop sizes - 128KB fills quickly :)
 
The new readme file looks great! :)

I will second or ... that... Looks great!

I have installed this beta and tried the new sdfat_usage...
Which worked for me :D

Note on your usage of the ls function... Wonder if you should pass in some flags...

Like I changed it when running it to: SD.sdfs.ls(LS_DATE | LS_SIZE);

Output on mine now looks like:
Code:
Initializing SD card...initialization done.

Print directory using SD functions
System Volume Information/
T4.1-Cardlike.jpg                         393481
T4-Cardlike.jpg                           340510
OV7670.bmp                                307266
TL_01010003.tld                           1843200
TL_01010005.tld                           22272000
test1.txt                                 21
datalog.bin                               41943040

Print directory using SdFat ls() function
2020-11-02 05:18     393481 T4.1-Cardlike.jpg
2020-11-02 05:21     340510 T4-Cardlike.jpg
                     307266 OV7670.bmp
2019-01-01 00:03    1843200 TL_01010003.tld
2019-01-01 00:10   22272000 TL_01010005.tld
                         21 test1.txt
2021-01-01 00:00   41943040 datalog.bin

Writing to datalog.bin using SdFat functions
datalog.bin started with 41943040 bytes
  Allocate 40 megabytes for datalog.bin
Reading to datalog.bin using SD functions
  Read from file: Just some test data written to the file (by SdFat functions)

Again so far everything is working that I tried on this build
 
KurtE said:
Like I changed it when running it to: SD.sdfs.ls(LS_DATE | LS_SIZE);
Probably a good idea.

And thanks all for the compliments but did not really do much except copy what we already put together in all the examples. Oh just one note, can't really add any more to readme - looks like there is a limit on the size unless I did something wrong.
 
Posted LittleFS Examples/Integrity update on thread : pjrc.com/threads/58033-LittleFS-port-to-Teensy-SPIFlash

Next is SPI after pushing cleanup on #4 back to the first 3 :( - then seems I need to Add PROG_MEM native FLASH example.

And noted there - do I ifdef NAND .vs. NOR in same examples - or add two more variants? Simple variants allow 100% function without edit ( except SPI CS ).
 
@Paul / @all: cleanup effort posted for LittleFS Integrity Media specific sketches

See LittleFS-port-to-Teensy-SPIFlash

Code:
T:\arduino-1.8.15\hardware\teensy\avr\libraries\LittleFS\examples\Integrity>dir /b
ALL
[B]MRAMSPI
PROG
PSRAM
QSPI
RAM
SPI[/B]

Help Re-Org:
Code:
 1-9 '#' passes continue Loop before Pause
 'c, or 0': Continuous Loop, or stop Loop in progress
 'h, or k': start Hundred or Thousand Loops
 'd' Directory of LittleFS Media
 'D' Walk all Dir Files verify Read Size
 'l' Show count of loop()'s, Bytes Read,Written
 'B, or b': Make Big file half of free space, or remove all Big files
 'S, or s': Make 2MB file , or remove all 2MB files
 	>> Media Format : 'q' and 'F' remove ALL FS data
 'q' Quick Format Disk 
 'F' Low Level Format Disk 
 'w' WIPE ALL Directories and Files
 'm' Make ROOT dirs (needed after q/F format or 'w')
 'f' LittleFS::formatUnused( ALL ) : DATA PRESERVED, empty blocks preformatted 
 'a' Auto formatUnused() during Loop - TOGGLE
 'y' reclaim 1 block :: myfs.formatUnused( 1 )
 'Y' reclaim 15 blocks :: myfs.formatUnused( 15 )
 	>> Test Features 
 'g' run SpeedBench() Media speed benchmark
 'x' Directory filecount verify - TOGGLE
 'v' Verbose All Dir Prints - TOGGLE
 'p' Pause after all Dir prints - TOGGLE
 'n' No verify on Write- TOGGLE
 'u' Update Filecount
 'R' Restart Teensy - Except 'RAM' - data persists
 '+, or -': more, or less add .vs. delete in Loop
 '?' Help list : A Loop will Create, Extend, or Delete files to verify Integrity
 
NativeEthernet

1.54 Beta 12 installed fine on clean new 1.8.15. However, it has not resolved one major problem: NativeEthernet's unreliability.


Well, based on my experiments, I am inclined to say, that Teensy 4.1 is unsuitable for all applications which use Ethernet heavily as Ethernet processing stops after some time or crashes the processor completely from time to time. Of course, one can use Teensy 4.1's great watchdog to restart an application, when NativeEthernet has brought processing or it to a standstill, but this is not my understanding of a watchdog's real purpose. A real-time processing must run and not stall or restart frequently because of faulty code.

If you scan the forum, you will find quite a few unresolved contributions, where users have described the fact that NativeEthernet is unreliable. Considering that Paul S. has written Arduino's great (new version 2) Ethernet library, I simply cannot comprehend, why there seems no obvious activity to get to the bottom of the issue. Of course, one could say, that Teensy 4.1 is hardware and all libraries are just "as they are", and therefore users have to accept that they might run out of luck, if a major feature isn't reliably working. However, why producing T4.1 over T4, if users cannot rely on its native Ethernet?


Based on my trials, there are applications which can use NativeEthernet: these seem to be applications which either use just EthernetServer or EthernetClient and (!!!) have minimal Ethernet traffic. All others fail after a while, be it after a few minutes or hours.


Let me explain in more depth, what I found so far: I have ported one application from Arduino Mega and two from Due to Teensy 4.1, all using a combination of EthernetServer and EthernetClient. One acts mainly as Server (with little traffic), connecting once every 10 mins to another T4.1 based Server as Client; the second is equally a Server with rare traffic, but connects once per minute as Client. The third, the one which makes me pulling out my hair, acts heavily as Server and as Client. The result: The first two rarely stop (but they stop), whilst the third crashes every few hours.

I assumed that the error must be mine, ignoring the fact that basically the very same applications had successfully run for several years(!) non-stop and without any watchdog on Arduino Mega and Arduino Due. Well, in the end I have given up on the third one and ported it back to Arduino Due, where it now runs again since many days without any issue.


Nevertheless, I wanted to understand the issue in more depth, and therefore made more investigations. I observed the following errors:

a) EthernetServer stops, meaning T4.1 does no longer accept incoming requests, whilst outside calls are still working.
b) the opposite, i.e. incoming calls are still served, whilst outgoing calls have stopped.
c) T4.1 stops altogether (watchdog timeout >30secs)
d) T4.1 can stop if the Sever, it connects to is restarted. It might have connected but awaits forever (> watchdog timeout) for an answer (no unprotected while() in my code!)

In case a) and b) I have seen that NativeEthernet had run out of sockets, indication that the library's internal socket management has failed. Increasing the number of available sockets to 12 did not help, only delay the stall. In those cases c), I have seen happening, the socket count was below maxSocket.

I have not been able to monitor all crashes as I did not look at USB Serial at all times. Important to note. I have very, very rarely seen SendErr:-20 in my applications, which all have been amended to make sure that all incoming data is read, client.close() and client.stop() are used.

In order to get to the bottom, I have programmed an Arduino Due + Ethernetshield v2 to act as an EthernetServer and EthernetClient, the Client connection to a heating controller every 17seconds, from which it receives around 810bytes. Furthermore, I programmed an Arduino Mega + EthernetShield v2 to emulate a server, connecting to this T4.1. Whilst this is far from my real application, which exchanges traffic between many other Arduino and two Teensy 4.1 microcontrollers + a Windows Server, running several .aspx applications, it might be of help.

All the Mega Client sends is "client.println("GET /PgEsNxx"); client.println();" with xx being 11, 22, 33....99. These 10 requests are made every 5 secs, 10ms apart. The burst of client.connects are made to simulate several requests, usually coming from different sources, but could of course coincide in time. This application performed perfectly without any issue on these Arduinos.


In the next experiment I replaced the Due with a T4.1, and it became immediately obvious, that a too short time difference between two consecutive requests, lead to SendErr: -20, despite having made certain that T4.1 had read all incoming bytes and my application had run client.close() before client.stop(). I therefore increased the time between two requests to 50ms, although in real usage, when requests can come from different sources, this could not be guaranteed. Further investigation revealed that (one of) the problems seem to be, that T4.1 is very slow in answering a request - and not because it did not connect in time or was heavily loaded. Even allowing on the receiving server 25ms, there were occurrences where less than 10 bytes had been received. It wouldn't be too unexpected if some Server timed out, assuming that no more data was coming. Note in this case, that my application sends Data in client.print("abcd") packets and not in a buffer.

As it seems to me - maybe this is too naively seen - the response is send out by T4.1 asynchronously with the application code, as the whole sending (in my example's code) takes less than 1ms. It might mean - I guess - that another Server response is has already started whilst the former connection is still being completed. Maybe this could explain the Socket miscount, I reported above?


In cases, where T4.1 was unable to send all its information, it created those "SendErr: -20", which have been reported before. It means to me, that the fix to add client.close(), as suggested before, isn't the correct or only necessary fix. Basically, this error message appears if T4.1 cannot fully send its information. Whilst seeing message SendErr: -20 might be annoying, it simply reflects that the connecting client has given up before "slow" T4.1 has completed it's sending. Considering the tiny workload of my example, I think, it shouldn't take T4.1 so long to send out a few bytes. Having said all this, as said above, SendErr:-20 are not seen in my real applications, so they are not the (main) culprit in my application.


Having added a sufficient long waiting at the Client, I got rid of most SendErr:-20, but unfortunately, as in my real applications, T4.1 stopped completely after approx. 90mins for the first. Something which could be repeated.
Next I disabled (commented out sendPowerToMYPV2(0,500); )the use of EthernetClient to make it easier for you to reproduce the error. It still stalls the T4.1 albeit it takes much more time before the T4.1 stalls. In these experiments, one can see, how the SocketNumber slowly increases.
Example: at start and 3.25h later

07:14:54.266 -> GETPgEsN66 Action:20 SkNr@Start:0 additional Info rxed: = None client.close done SNrP1:0 client.stop executed SkNr@End:8 dt_ms: 0

10:28:15.652 -> GETPgEsN66 Action:20 SkNr@Start:4 additional Info rxed: = None client.close done SNrP1:4 client.stop executed SkNr@End:8 dt_ms: 0


Looking at everything, the clue might be the processing of requests which are close together in time, considering that the process partially takes place at different places of T4.1!? And as it seems, using EthernetClient whilst receiving several incoming requests close together in time, might cause the error more frequently.



Teensy 4.1 is a great controller, at least in instances where no Ethernet or rare Ethernet is required. It might be a little heavy on RAM usage compared to Arduino Due, but that might be due to its relative new existence. I truly hope, PJRC undertakes effort to resolve the weakness of T4.1 Ethernet library as at present, it cannot challenge "old" Arduino Due when it comes to "heavier" Ethernet work.

Please do not get me wrong: I truly appreciate the hard work which has gone into NativeEthernet or indeed any other software, but I see Ethernet as one key feature of T4.1 and therefore -in my opinion- already too much time has passed without experts' assistance and contribution to this multiple reported weakness. We, users of Teensy are not necessarily the experts who are albe to dive deep into complex libraries, particularly those which are close to Teensy's core architecture. Well, we might even be at fault, when we merely pass our experience from Arduino into Teensy, but that too means, we need experts' assistance.

P.S. don't be surprised to see many "unused" variables in my code, that code is a snippet out of a rather lengthy application. It should hopefully help to reproduce the issue.

Here is the T4.1 code
Code:
#define useClientClose 1

#include <Wire.h>
#include <SPI.h>
#include <NativeEthernet.h>

#include <elapsedMillis.h>

#include <TimeLib.h>

byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x2A, 0x1B };

IPAddress ip(192, 168, 2, 11);
IPAddress gateway(192,168,2, 1);
IPAddress subnet(255, 255, 255, 0);

EthernetServer server(9010);


//IGNORE the following parameters, they remain here, as I cut this software from my major lengthy application
      int PowerHeliotherm=0;
      boolean allowThorAlways=true;
      unsigned long PowerDownThorAsLongNoActivity=0;
      int min_MYPV_Power_On=30;
      float factorThor=0.862;
      int ThorAskedNothing=0;                                 
      int max_ThorAskedNothing=240;                       
      float Parameter[275];
      int ParameterNrDerPowerForTHOR=0;
      boolean PowerThorUpAsThorWantsToWork=false;
      boolean bDruck_sendPowerToMYPV=true;
      int ErrorCounterACThor=0;                                
      int maxErrorCounterACThor=125;                           
      boolean ConnectionToThorOK=true;
      float LastThorPowerSent=0;                               
      boolean GotAZeroBackFromThor=true;
      int powerSentToThorSinceLastContactToPC=0;                  
      int AnzahlDerMessungen=0;                                   
      int HelioAlert=0;
      int LEDred=13;
      int LEDyellow=14;
      unsigned long LEDred_maxOn=1000;
      boolean showThorDetails=true;
      unsigned long Jetzt=0;
      byte OutBuffer[45];
      unsigned long Zeit_topowerDOWN_LEDyellow_PCC=0;
      unsigned long timeLastPC_Contact_Request_made=0;
      int counter_ServerContactLastMinute=0;
      const byte showDataExchangeToRx          =0;  //zeigt Main Kommunikation mit PC geschickt wird 
      const byte showDataExchangeToRx2         =0;  //zeigt Rest Kommunikation mit PC geschickt wird 
      const byte showDataExchangeToRxText      =0;  //zeigt Datenn die zum PC geschickt wird 
      const byte maxPowerMeasurements=10;
      float fPges[1441][maxPowerMeasurements];    
      boolean firstPges[maxPowerMeasurements]={false, false, false, false, false, false, false, false, false, false};  
      boolean ItsMidNight[maxPowerMeasurements]={false, false, false, false, false, false, false, false, false, false}; 
      unsigned int dayCounter[maxPowerMeasurements]={0,0,0,0,0,0,0,0,0,0};
      int NrAtMidNight[maxPowerMeasurements]={9999,9999,9999,9999,9999,9999,9999,9999,9999,9999};                
      boolean NotFirstLoop=false;
      float old_Ehour[maxPowerMeasurements]    = {9999,9999,9999,9999,9999,9999,9999,9999,9999,9999};
      float old_Eday[maxPowerMeasurements]     = {9999,9999,9999,9999,9999,9999,9999,9999,9999,9999};
      float old_Eweek[maxPowerMeasurements]    = {9999,9999,9999,9999,9999,9999,9999,9999,9999,9999};
      float old_Emonth[maxPowerMeasurements]   = {9999,9999,9999,9999,9999,9999,9999,9999,9999,9999};
      float Estunde[24][maxPowerMeasurements];  //hier speichern wir die stündlichen Summen ab
      float old_Estunde[24][maxPowerMeasurements];  //hier speichern wir die stündlichen Summen ab
      int counterEstunde[maxPowerMeasurements]={0,0,0,0,0,0,0,0,0,0};
      int counterEtag[maxPowerMeasurements]={0,0,0,0,0,0,0,0,0,0};
      int ErrorCounter[maxPowerMeasurements]={0,0,0,0,0,0,0,0,0,0};
      int old_ErrorCounter[maxPowerMeasurements]={0,0,0,0,0,0,0,0,0,0};
      float Etag[maxPowerMeasurements];           //hier speichern wir die laufende Tagessumme ab, dh Summe aller Messwerte durch Anzahl der Messwert
      float oldEtag[maxPowerMeasurements];        //hier den gestrigen Wert, so dass wir ihn nach Miternacht für 24 Stunden abrufen können
      byte letzteStunde=26;
      byte dieseStunde =25;
      boolean fPgesMemoryOverflow[maxPowerMeasurements]={false, false, false, false, false, false, false, false, false, false};
      boolean old_fPgesMemoryOverflow[maxPowerMeasurements]={false, false, false, false, false, false, false, false, false, false};
      byte ConversionLfdNrZuParameterNr[maxPowerMeasurements]={0,1,2,15,16,17,18,35,36,37};
      float LastPowerMeasurement[maxPowerMeasurements];
      float AverageBezug1Minute=0;   int CountBezug1Minute=0;
      float AverageLieferung1Minute=0;  int CountLieferung1Minute=0;
      float lastAverageBezug1Minute=0;  
      float lastAverageLieferung1Minute=0;  
      int EndSwitches=10;
      int startCO2=15;
      int SendErrorMsg1=5;
      int SunRiseMinAfterMidnight=400;
      int SunSetMinAfterMidnight=800;
      int ThorStatusForPrintInClock=0;
      int PowerUsedByMYPV=3459;
      int max_MYPV_Power_Used=3500;
      float T_wellness_1=38;
      float T_wellness_2=39.5; 
      float Vbat_Wellness=4.55;
      int NewInfoType=2;
      int WasserVerbrauchToday=850;
      byte KlimaOnOff=1;
      float  oldGeniaxKorrekturSimple=21;
      float GeniaxKorrekturSimple=21.5;
      byte cVorne_GeniaxKorrekturSimple  = 0;
      byte cHinten_GeniaxKorrekturSimple =0;
      byte cVorne_GeniaxKorrekturComplex  = 0;
      byte cHinten_GeniaxKorrekturComplex =0;
      float oldGeniaxKorrekturComplex=0;
      float GeniaxKorrekturComplex=0;
      int SolarPowerNow=0;
      unsigned long Left_PC_Contact=0;
      unsigned long timeOutCall=0;
      boolean useClientClose_PC_Contact=true;
              
             
void setup() 
{
   Serial.begin(250000);

    //Ignore these inits, they are caused by my snippet
    OutBuffer[ 0]=0x47; OutBuffer[ 1]=0x45; OutBuffer[ 2]=0x54; OutBuffer[ 3]=0x20; OutBuffer[ 4]=0x2F; OutBuffer[ 5]=0x63; OutBuffer[ 6]=0x6F; OutBuffer[ 7]=0x6E; OutBuffer[ 8]=0x74; OutBuffer[ 9]=0x72;        //GET /contr
    OutBuffer[10]=0x6F; OutBuffer[11]=0x6C; OutBuffer[12]=0x2E; OutBuffer[13]=0x68; OutBuffer[14]=0x74; OutBuffer[15]=0x6D; OutBuffer[16]=0x6C; OutBuffer[17]=0x3F; OutBuffer[18]=0x70; OutBuffer[19]=0x6F;        //ol.html?po
    OutBuffer[20]=0x77; OutBuffer[21]=0x65; OutBuffer[22]=0x72; OutBuffer[23]=0x3D; 
    Parameter[0]=1;
    pinMode(LEDred,OUTPUT); 
    pinMode(LEDyellow,OUTPUT); 
   
  
    Serial.println(F("connecting to Ethernet"));
                       
    pinMode(4,OUTPUT); digitalWrite(4,HIGH);
    Ethernet.begin(mac, ip, gateway, subnet);

    //server.begin();      //start listening for clients on EThernet         

     delay(1000);
  
}

void loop() 
{
   if(millis()-timeOutCall>17000)
   {

      //sendPowerToMYPV2(0,500);          
      
      timeOutCall=millis();
   }

   PCContact();
   
   delay(1);
   
}

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void PCContact()
{   
          char ReadText[120];    
          byte Count=0;
          byte Action=99; 

      
          long t1=millis(); 
    
              Ethernet.setRetransmissionCount(1);    //<------------------------------------------------------------------------------------------------------------------- 
              Ethernet.setRetransmissionTimeout(50); //<-------------------------------------------------------------------------------------------------------------------

              EthernetClient client = server.available();
 
              client.setConnectionTimeout(25); 

              boolean ExtraLine=false;
 
 
  
  
  if (client) 
  {
           
  
           //wait for Data from client   
           elapsedMillis waitPC1; 

           //wait for Server to connect      
           while(!client.available() && waitPC1 < 10000)
           {
             delayMicroseconds(1);

             if(waitPC1>16 && waitPC1%16==0) checkSerial1_for_KNX(); 
           }
  
           if(waitPC1 > 1000) {Serial.print("waitPC1: "); Serial.print(waitPC1); Serial.print("\tBytes:"); Serial.println(client.available());}     //INFO ONLY
           
                                                       
         
                    
                if (client.available())
                { 
                      Serial.println();
                      
                      while(client.available() && Count<95 )
                      {
                           ReadText[Count] = client.read();
                                       if(ReadText[Count]>48) Serial.print(ReadText[Count]);            
                           Count++;
                      }
                                 
            
                                        
                                     
                          
                                   if(ReadText[0]=='G' && ReadText[1]=='E' && ReadText[2]=='T') 
                                   {  
                                     
                                        Action = AnalyseGet(ReadText);     //Decode Get Information
                                    
                                        boolean currentLineIsBlank = true;
                                       
                                        int Limiter=0;
                                        
                                               
                                                     
                                                    //In case we haven't already read everything                                      
                                                    while(client.available() && Limiter<120) 
                                                    {
                                                      char c = client.read();   Serial.print(c);             // see what has been received     
                                                          
                                                       if (c == '\n')
                                                       {   
                                                            currentLineIsBlank = true;      // you're starting a new line
                                                        }
                                                        else if (c != '\r')
                                                        { 
                                                            currentLineIsBlank = false;     // you've gotten a character on the current line
                                                        }
                    
                                                        if (c == '\n' && currentLineIsBlank) break;
                                                          
                                                        Limiter++; 
                                                        
                                                    } 
                                                    
                                                                               
                                                  //Response - usually this connection goes to a true HTTP Server                                                                                                                                         
                                                                                                                                                                 
                                                  client.println(F("HTTp/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(F("Connnection: close")); client.println();

                                                                       
                                                 
                                                  Serial.print("\tAction:"); Serial.print(Action); byte SockNr = client.getSocketNumber();  Serial.print("\tSkNr@Start:"); Serial.print(SockNr);                  

                                                 
                                                 switch (Action) 
                                                 {
                                                   
                                                    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
                                                    case 0: //Info not understood
                                                    {
                                                       Serial.print(F("\n\n\tCannot decode PC's GET Request. RXed:   ")); Serial.print(ReadText); Serial.print(F("  Count="));Serial.println(Count);
                                                       client.println(F("NOK"));
                                                       break;
                                                    }

                                                                                                      
                                                    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
                                                    case 99: //favicon - nothing to do
                                                    {
                                                      Serial.println(F("Favicon"));
                                                      break;
                                                    }

                                                   
                                                    //====================================================================================================================================================================
                                                    case 20: //sende Pges Daten an den PC
                                                    {
                                                               //There is nothing special about this case 20, it has been stripped from my major application for this test - it basically sends 
                                                               //in this test example : 0$0.00$0.00$0.00$0.00$0$27$53$1$1$1970$0$0.00$0$0.00$0.00$DATA$DATA
                                                               
                                                               
                                                               //   else if(ReadText[5]=='P' && ReadText[6]=='g' && ReadText[7]=='E' && ReadText[8]=='s' && ReadText[9]=='N')                       bReturn=20;   //Messwerte der letzten Zeit senden
              
                                                               //GET /PgEsNpq_FabcdTvxyz$VAB$
                                                               //012345678901234567890123
                                                               
                                                              
                                                               if(ReadText[10]!=ReadText[11] || ReadText[10]<48 || ReadText[10]>57) {Serial.print(F("Invalid Request: ")); Serial.println(ReadText); break;}
              
              
                                                               int PNr= ReadText[10] -48; 
                                                                  
                                                               int StartIndex=0; int EndIndex=dayCounter[PNr]; 
                      
                                                               //bei partieller Anfrage gilt GET /PgEsNpq_FabcdTvxyz$VAB$
                                                               //                            012345678901234567890123
                                                               //                            p=q  ParameterNr
                                                               //                                         FROM
                                                               //                                              To    .it VAB=V-1 für gestern

                                                               if(PNr==9) ExtraLine=true;
                                                        
                                                     
                                                       if(ReadText[13]=='F' &&  ReadText[18]=='T' && ReadText[23]=='$')
                                                       { 
                                                           int S=0;
                                                           int E=  dayCounter[PNr];
                                                          
                                                          //partielle Anfrage
                                                          if(   (ReadText[14]=='0' || ReadText[14]=='1') && ReadText[15]>=48 && ReadText[15]<=57 && ReadText[16]>=48 && ReadText[16]<=57 && ReadText[17]>=48 && ReadText[17]<=57)
                                                          {
                                                              S = (ReadText[14]-48)*1000 + (ReadText[15]-48)*100 + (ReadText[16]-48)*10 + (ReadText[17]-48); 
                                                           
                                                          }
                                                          else
                                                          {
                                                            //Serial.print(F("14 15 16 17: ")); Serial.print(ReadText[14]); Serial.print(ReadText[15]); Serial.print(ReadText[16]); Serial.println(ReadText[17]); 
                                                          }
                                                              
              
                                                                 
                                                                  if(ReadText[19]!='x' ||  ReadText[20]!='x' || ReadText[21]!='x' || ReadText[22]!='x' )
                                                                  {  
                                                                    if( (ReadText[19]=='0' || ReadText[19]=='1') && ReadText[20]>=48 && ReadText[20]<=57 && ReadText[21]>=48 && ReadText[21]<=57 && ReadText[22]>=48 && ReadText[22]<=57 )
                                                                    {
                                                                      E = (ReadText[19]-48)*1000 + (ReadText[20]-48)*100 + (ReadText[21]-48)*10 + (ReadText[22]-48); 
                                                                    }
                                                                  }
                                                                      else
                                                                  {
                                                                    //Serial.print(F("19 20 21 22: ")); Serial.print(ReadText[19]); Serial.print(ReadText[20]); Serial.print(ReadText[21]); Serial.println(ReadText[22]); 
                                                                  }
                                                                  
                  
                                                                            if(E>=S)
                                                                            { 
                                                                               StartIndex=S; EndIndex=E;
                                                                            }
                                                                            else
                                                                            {
                                                                              //Serial.print(F("E: ")); Serial.print(E); Serial.print(F("  S: ")); Serial.println(S);
                                                                            }
              
                                                              
                                                       }
                                                       else
                                                       {
                                                        //Serial.print(F("13 18 23: ")); Serial.print(ReadText[13]); Serial.print(ReadText[18]); Serial.println(ReadText[23]); 
                                                        
                                                       }
                                                       
              
                                                     
                                                        //Serial.print(F("Pges["));  Serial.print(PNr); Serial.print(F("] -> PC   from: ")); Serial.print(StartIndex); Serial.print(F(" to ")); Serial.print(EndIndex); 
              
                                                        
                                                       if(ReadText[24]=='V' && ReadText[25]=='-' && ReadText[26]=='1' )
                                                       {
                                                           client.print(dayCounter[PNr]); client.print(F("$"));
                                                          
                                                           client.print(Parameter[267]); client.print(F("$"));
                                                           client.print(Parameter[268]); client.print(F("$"));
                                                           client.print(Parameter[269]); client.print(F("$"));

                                                           
                                                           client.print(LastPowerMeasurement[PNr]); client.print(F("$"));
                                                           client.print(hour()); client.print(F("$"));
                                                           client.print(minute()); client.print(F("$"));
                                                           client.print(second()); client.print(F("$"));
                                                           client.print(day()); client.print(F("$"));
                                                           client.print(month()); client.print(F("$"));
                                                           client.print(year()); client.print(F("$"));
                  
                                                           client.print(counterEstunde[PNr]); client.print(F("$"));
                                                           client.print(Estunde[letzteStunde][PNr]); client.print(F("$"));
                                                              
                                                           client.print(counterEtag[PNr]); client.print(F("$"));
                                                           client.print(Etag[PNr]); client.print(F("$"));
                                                           client.print(Parameter[EndSwitches+1]);                                                 
                                                           client.print(F("$DATA$"));
                                                           
                  
                  
                                                                                                    
                                                           for (int i=StartIndex; i< EndIndex; i++)
                                                           {
                                                             client.print(F("$"));
                  
                                                             if(i%100==0) checkSerial1_for_KNX();
                                                           }
                  
                                                           client.print(F("DATA"));
                                                       }
                                                       else
                                                       {
                                                                client.print(dayCounter[PNr]); client.print(F("$"));
                                                                client.print(Parameter[267]); client.print(F("$"));
                                                                client.print(Parameter[268]); client.print(F("$"));
                                                                client.print(Parameter[269]); client.print(F("$"));
                                                               
                                                               client.print(LastPowerMeasurement[PNr]); client.print(F("$"));
                                                               client.print(hour()); client.print(F("$"));
                                                               client.print(minute()); client.print(F("$"));
                                                               client.print(second()); client.print(F("$"));
                                                               client.print(day()); client.print(F("$"));
                                                               client.print(month()); client.print(F("$"));
                                                               client.print(year()); client.print(F("$"));
                  
                                                               client.print(counterEstunde[PNr]); client.print(F("$"));
                                                               client.print(Estunde[letzteStunde][PNr]); client.print(F("$"));
                                                              
                                                               client.print(counterEtag[PNr]); client.print(F("$"));
                                                               client.print(Etag[PNr]);  client.print(F("$"));
                                                               client.print(Parameter[EndSwitches+1]); client.print(F("$DATA$"));
                                                                     
                  
                                                                                                    
                                                            for (int i=StartIndex; i< EndIndex; i++)
                                                            {
                                                               client.print(fPges[i][PNr],4);
                                                               client.print(F("$"));
                  
                                                               if(i%100==0) checkSerial1_for_KNX();
                                                           }
                  
                                                            client.print(F("DATA"));
                                                       }
                                                       
                                                       break;
                                                       
                                                    }
              
              
                                                  
                      
                                                    
                                                    //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
                                                    default: 
                                                    {
                                                      break;
                                                    }
                                           
                                                 } //end e switch(Action)
                                         
                                        
                                            
                                    ReadText[0]=0;
                                    
                                   
                                                 
                               }  //ENDE else if(ReadText[0]=='G' && ReadText[1]=='E' && ReadText[2]=='T') 
                               
                              
                     }    //end  if(client.available())
                                 





                                 Serial.print(F("\t\tadditional Info rxed: "));
                 
                                 int addC=0;
                                 while(client.available())
                                 {
                                    char c=client.read(); Serial.print("0x");Serial.print(c, HEX); Serial.print(" ");
                                    addC++;
                                 }
  
                                 if(addC>2) {Serial.print(" = Nr of Bytes:"); Serial.print(addC); }  else Serial.print(F(" = None"));       

                                 
  

                                         #if defined (useClientClose)
                                            
                                               if( useClientClose_PC_Contact)
                                               {
                                                    client.close(); Serial.print("\tclient.close done"); 
              
                                                     byte SockNr = client.getSocketNumber(); Serial.print("  SNrP1:"); Serial.print(SockNr);  
                                               }
                                               
                                         #endif

                                         
                                                                       
                                 client.stop(); Serial.print("\tclient.stop executed");  byte SockNr = client.getSocketNumber(); Serial.print("  SkNr@End:"); Serial.print(SockNr);  
  
                                 Serial.print(F("\tdt_ms: ")); Serial.println(millis()-t1);    
                                 
                                 if(ExtraLine) Serial.println();
     
          }  //end   if(client) 
        
             
                
          
          

          

       
} //End Routine


  



//----------------------------------------------------------------------------------------------------------------------------
byte AnalyseGet(char ReadText[])
{
  
  byte bReturn=0;


  if(ReadText[3]==' ' && ReadText[4]=='/')
  {
  
       

        if (ReadText[5]=='f' && ReadText[6]=='a' && ReadText[7]=='v' && ReadText[8]=='i' && ReadText[9]=='c' && ReadText[10]=='o' )   bReturn=99;   //Favicon ignore  

        else if(ReadText[5]=='P' && ReadText[6]=='g' && ReadText[7]=='E' && ReadText[8]=='s' && ReadText[9]=='N')                     bReturn=20;   //Messwerte der letzten Zeit senden

        
        
  }
 
   
  return bReturn;
}  

//==============================================================================================================================================================================================================================

int sendPowerToMYPV2(float DataToSend, float MaxData)
{

    //This routine connects to a Server, which responds typically in 65ms and then sends ~810 bytes within 2.5ms.

    
                                                                                          //if(Parameter[ParameterNrDerPowerForTHOR]==0) {Serial.print(F("\n\tThor IS POWERED OFF")); return 0;}

              byte OutBuffer[45];
              
              OutBuffer[ 0]=0x47; OutBuffer[ 1]=0x45; OutBuffer[ 2]=0x54; OutBuffer[ 3]=0x20; OutBuffer[ 4]=0x2F; OutBuffer[ 5]=0x63; OutBuffer[ 6]=0x6F; OutBuffer[ 7]=0x6E; OutBuffer[ 8]=0x74; OutBuffer[ 9]=0x72;        //GET /contr
              OutBuffer[10]=0x6F; OutBuffer[11]=0x6C; OutBuffer[12]=0x2E; OutBuffer[13]=0x68; OutBuffer[14]=0x74; OutBuffer[15]=0x6D; OutBuffer[16]=0x6C; OutBuffer[17]=0x3F; OutBuffer[18]=0x70; OutBuffer[19]=0x6F;        //ol.html?po
              OutBuffer[20]=0x77; OutBuffer[21]=0x65; OutBuffer[22]=0x72; OutBuffer[23]=0x3D; 


        //Ist Thor allowed, if not show this
  
                  Serial.print(F("\n\t")); Serial.print(DataToSend); Serial.print(F("->Thor"));  Serial.print(F("  Max:")); Serial.print(MaxData);   

                  if(PowerHeliotherm > 0 && PowerHeliotherm < 9000 && allowThorAlways==false) {Serial.print(F("  Helio ON & allowThorAlways=false -> Send 0")); MaxData=0; }


        //Thor is active, allowed to fire
  
          unsigned long Jetzt=millis();

          byte ThorBuffer[900];  int len=0;


              //Ausgabewert gegen Grenzwerte checken und bei Bedarf beschränken

                   if(DataToSend > MaxData) DataToSend= MaxData;  
              else if(DataToSend < min_MYPV_Power_On) DataToSend = 0; 

             //korrigiert, die Wattzahl, in die von Thor benötigte, denn Thor geht von 100% = 3kW aus
                  
                  DataToSend=DataToSend/factorThor;  
                  int iData=int(DataToSend);      


        //Sicherheitsabfrage gegen negative Werte und Uhr starten,die die Zeit des letzten positiven Requesta an Thor zeigt  
               
        if(iData > 0)  
        {
           PowerDownThorAsLongNoActivity = millis();   //compare against  + max_PowerDownThorAsLongNoActivity    denn thor schaltet nach dieser Zeit ab, wenn es keine Thor Leistung in diesem Intervall gab

           ThorAskedNothing=0;

           //Ist Thor noch aus, dann macht dieser Request keinen Sinn, aber über das Flag PowerThorUpAsThorWantsToWork wird Thor gestartet werden
           if(Parameter[ParameterNrDerPowerForTHOR]==0) { PowerThorUpAsThorWantsToWork=true; return 0;}
        }
        else
        {
          ThorAskedNothing++;
        }
         
                              Serial.print(F("\t-> iPwr:")); Serial.print(iData); 
                              

        //Zuviele Requests der Größe 0 (oder kleiner) wurden nacheinander gemacht, in diesem Fall können wir Thor einfach nicht länger ansteuern, denn dann geht dieser sowieso nach 0
        
        if(ThorAskedNothing > max_ThorAskedNothing)
        {
           ThorAskedNothing--;

           Serial.print(F("  > ")); Serial.print(max_ThorAskedNothing); Serial.println(F(" ZeroPWR an Thor -> stop sending until >0 again"));
           
           return 0;
        }

        

        //Jetzt haben wir einen Wert, den wir an Thor senden wollen

              const byte mypv[] = {192, 168, 2, 172};  
              
       
        


        //OUTPUT BUFFER mit Payload versehen
            
            
                                          //Started in Setup by:
                                          //         void init_Thor_OutBuffer()
                                          //         {
                                          //              OutBuffer[ 0]=0x47; OutBuffer[ 1]=0x45; OutBuffer[ 2]=0x54; OutBuffer[ 3]=0x20; OutBuffer[ 4]=0x2F; OutBuffer[ 5]=0x63; OutBuffer[ 6]=0x6F; OutBuffer[ 7]=0x6E; OutBuffer[ 8]=0x74; OutBuffer[ 9]=0x72;        //GET /contr
                                          //              OutBuffer[10]=0x6F; OutBuffer[11]=0x6C; OutBuffer[12]=0x2E; OutBuffer[13]=0x68; OutBuffer[14]=0x74; OutBuffer[15]=0x6D; OutBuffer[16]=0x6C; OutBuffer[17]=0x3F; OutBuffer[18]=0x70; OutBuffer[19]=0x6F;        //ol.html?po
                                          //              OutBuffer[20]=0x77; OutBuffer[21]=0x65; OutBuffer[22]=0x72; OutBuffer[23]=0x3D;                                                                                                                               //wer=
                                          //         }
                                          

                   int W=iData;         int index=28;
                   
                   if(W>=1000)
                   {
                      int T=W/1000;  byte bT=byte(T);          W=W-T*1000;
          
                      int H=W/100;   byte bH=byte(H);          W=W-H*100;
          
                      int Z=W/10;    byte bZ=byte(Z);          W=W-Z*10;
          
                      int E=W;      byte bE=byte(E);           OutBuffer[24]=bT+48;  OutBuffer[25]=bH+48;  OutBuffer[26]=bZ+48;  OutBuffer[27]=bE+48; 
                   }
          
                   else if(W>=100)
                   {
                      index=27;
          
                      int H=W/100;   byte bH=byte(H);          W=W-H*100;
          
                      int Z=W/10;    byte bZ=byte(Z);          W=W-Z*10;
          
                      int E=W;      byte bE=byte(E);           OutBuffer[24]=bH+48;  OutBuffer[25]=bZ+48;  OutBuffer[26]=bE+48;
                   }
          
                   else if(W>=10)
                   {
                      index=26;
          
                      int Z=W/10;    byte bZ=byte(Z);         W=W-Z*10;
          
                      int E=W;      byte bE=byte(E);          OutBuffer[24]=bZ+48;  OutBuffer[25]=bE+48;  
                   }
          
                   else
                   {
                     index=25;  byte bE=byte(W);              OutBuffer[24]=bE+48;    
                   }
          
                   OutBuffer[index  ]=0x20; OutBuffer[index+ 1]=0x48;  OutBuffer[index+ 2]=0x54; OutBuffer[index+3 ]=0x54; OutBuffer[index+4]=0x50; OutBuffer[index+5]=0x2F; OutBuffer[index+6]=0x31; OutBuffer[index+7]=0x2E; OutBuffer[index+8]=0x31; // blank HTTP/1.1
                   OutBuffer[index+9]=0x0D; OutBuffer[index+10]=0x0A;  OutBuffer[index+11]=0x0D; OutBuffer[index+12]=0x0A;
         

                              //Serial.print("OutBuffer: ");  for(int i=0; i<index+13;i++) {Serial.print(OutBuffer[i],HEX); Serial.print(" "); } Serial.println();

                       
                       

        //Fertig nun zum Senden an Thor
         
         EthernetClient client;

                               
                     Ethernet.setRetransmissionCount(1);     //<------------------------------------------------------------------------------------------------------------------- 
                     Ethernet.setRetransmissionTimeout(50);  //<------------------------------------------------------------------------------------------------------------------- 
                     
                     
                     checkSerial1_for_KNX();    //um maximale Zeit zu haben


         
          

                                          boolean ReturnedOK=true;

                                          if(client.connect(mypv, 80)==1)
                                          {
                                                                                                                                                Serial.print(F("\tconnect OK"));
                                                                                                                                                byte SockNr = client.getSocketNumber(); Serial.print("  SkNr@Begin:"); Serial.print(SockNr); 

                                                                                                                                                
                                                    client.setConnectionTimeout(100);        //<------------------------------------------------------------------------------------------------------------------- 
                                                                                         
                                                      
                                                                                                                        
                                                           
                                                                  client.write(OutBuffer,index+13);
                                        
                                        
                                                                                  //auf Antwort warten
                                                                                  elapsedMillis wait;
                                                                                  while (len==0 && wait<500)
                                                                                  {
                                                                                     len = client.available();
                                                                                     checkSerial1_for_KNX(); 
                                                                                  }
                                        
                                        
                                                                                  //eine richtige Antwort hat ca. 807bytes
                                                                                              
                                        
                                                                                              if( (bDruck_sendPowerToMYPV && wait>65) || wait>75) {Serial.print("\tanswer after>65 || 75)ms: "); Serial.print(wait);  }    
                                        
                                                                                  len=client.available();       //sollten es noch mehr geworden sein
                                                                                  
                                                                                              if(bDruck_sendPowerToMYPV && (len<800 || len>830) ) {Serial.print("\tlen(>830||<800): "); Serial.print(len);  Serial.print("\t");}
                                        
                                                                                                                                                    
                                                                                                                                                                                                                                       Serial.print("\tlen:"); Serial.print(len);


                                                                                                    //wurden zuviele oder zuwenig Bytes empfangen
               
                
                                                                                                    if(len<600 || len>899)     //len zeigt die Gesamtlänge der Info an, die Thor gesendet hat, diese muss über 600 sein
                                                                                                    {
                                                                                                       ErrorCounterACThor++;
                                                                                    
                                                                                                       Serial.print(F("ErrorCounterACThor ++ to ")); Serial.print(ErrorCounterACThor); Serial.print(F("\tlen:")); Serial.println(len);
//                                                                                    
//                                                                                                       if(len>500)    //gab es irgendeine Info jenseits 500, dann zeigen wird dies hier an
//                                                                                                       {
//                                                                                                          for (int i=0; i<len; i++)  {Serial.write(buffer[i]);} Serial.println();  
//                                                                                                       }
                                                                                                       
                                                                                                       return 0; 
                                                                                                    }
                                                                                  

                                                                                                                                                
                                                                         client.read(ThorBuffer,len);       //nun lesen wir empfangene Daten
                                                                        
                                                                                  
                                                                                   //Lese den Rest, wenn es etwas gibt, ohne Abspecherung
                                                                                   wait=1; int addC=0;
                                                                                   
                                                                                   while(client.available() && wait<1000)
                                                                                   {
                                                                                      char c=client.read(); if(bDruck_sendPowerToMYPV) { if(addC==0) Serial.println("\n\t\tRest1: "); Serial.print(c,HEX); Serial.print(F(" ")); }  
                                                                                      addC++;
                                                  
                                                                                      if(wait%10==0) checkSerial1_for_KNX(); 
                                                                                   }
                                                    
                                                                                   if(addC>0) {Serial.print("\t(1)readRest:"); Serial.print(addC); Serial.print(" time:"); Serial.print(wait); }

                                                                                  
                                                                                  wait=0; addC=0;
                                                                                  while(client.connected() && wait < 1000)
                                                                                  {
                                                                                    addC++;
                                                                                    if(wait%10==0) checkSerial1_for_KNX(); 
                                                                                  }
                                                                                  
                                                                                  if(addC>0) {Serial.print("\t(1)stillconnected:"); Serial.print(wait); }


                                                        client.close();
                                                        
                                                        client.stop(); Serial.print("\tclient.stop done");                //delibrately outside  if(client.connect(mypv, 80)==1)

                                                        SockNr = client.getSocketNumber(); Serial.print("  SkNr@Stop:"); Serial.print(SockNr); 
                                                                                  

                                                       ConnectionToThorOK=true;
                                        }
                                        else
                                        {
                                           Serial.print("\tconnect NOK");
                                           ErrorCounterACThor++;
                                           ReturnedOK=false;

                                           ConnectionToThorOK=false;
                                           
                                        }

                                      


                if(len<360) 
                {
                   ErrorCounterACThor++;

                   Serial.print(F("ErrorCounterACThor ++ to ")); Serial.print(ErrorCounterACThor); Serial.print(F("\tlen:")); Serial.println(len);

                   if(len>0)
                   {
                      for (int i=0; i<len; i++)  {Serial.write(ThorBuffer[i]); }  
                   }
                   
                   return 0; 
                }
                



                      //Nun sollten wir gute Daten haben, wir durchsuchen den String nach Pow=
              
                      byte Power[5];
                
                      for (int i=350; i<len-100; i++) 
                      {
                           //Serial.print(ThorBuffer[i]);
                      
                          if( char(ThorBuffer[i])=='P' && char(ThorBuffer[i+1])=='o' && char(ThorBuffer[i+5])=='=')
                          {
                             Power[0]=ThorBuffer[i+6];    Power[1]=ThorBuffer[i+7]; Power[2]=ThorBuffer[i+8]; Power[3]=ThorBuffer[i+9];  Power[4]=ThorBuffer[i+10]; 
                                
                                                                                              
                                                                                              //Serial.print(F("i:")); Serial.println(i);
                             break;
                          }
                      }

                                                                 
                                                               //if(bDruck_sendPowerToMYPV) {Serial.print(F("Power:")); for(int i=0; i<5; i++) Serial.print(char(Power[i])); Serial.println();}
                                                                                    
                                                        
                                                                     



                
         

              

                //Wir analysieren, die Zahl, die Pow= folgen wird, diese kann 1 bis 4 stellig sein
               
                int j=0;  
                
                for(int i=0; i<5; i++) 
                {
                   if( char(Power[i]) == ' ')
                   {
                     j=i;
                     break;
                   }
                }


                          checkSerial1_for_KNX();
                      
              
                                                             //Serial.print(F("j:")); Serial.println(j);
              
                int iPower=9999;
                

                        //Bilden die Zahl
                        switch (j)
                        {
                           case 1: iPower=(Power[0]-48); break;
                      
                           case 2: iPower=(Power[0]-48)*10   +  (Power[1]-48); break;
                      
                           case 3: iPower=(Power[0]-48)*100  +  (Power[1]-48)*10   +  (Power[2]-48); break;
                      
                           case 4: iPower=(Power[0]-48)*1000 +  (Power[1]-48)*100  +  (Power[2]-48)*10 + Power[3]-48; break;
                      
                           default: if(ReturnedOK==false) iPower=0; else iPower=9999; break;
                           
                        }

               
                                     

                     if(iPower!=9999) ErrorCounterACThor=0;          //fehlerzähler zurücksetzen
                else if(ErrorCounterACThor!=0) {Serial.println(F("\t\tErrorCounterACThor:")); Serial.println(ErrorCounterACThor);}  //ggf aufgelaufene Fehler anzeigen

                

               
               //Serial Ausgabe  

               if(j!=0)
               {
                    Serial.print("\tThor retrnd: :"); Serial.print(iPower); 

                    if( (iPower<10 || MaxData==0)  && iData > 25  && LastThorPowerSent > 25) { Serial.print(F(" GotAZeroBackFromThor->true ")); GotAZeroBackFromThor=true; }

                
                    //Mittlere Power errechnen, die Thor ausgab, seit letzeter Übermittelung an Website
     
                    powerSentToThorSinceLastContactToPC+=iPower;
                    AnzahlDerMessungen++;
    
                    Serial.print("\t\t<P(sent)>: "); Serial.print(powerSentToThorSinceLastContactToPC/AnzahlDerMessungen);

               }
               else
               {
                    Serial.println(F("\tThor contact failed"));
               }

                unsigned long ComTimeForDefault = millis()-Jetzt;   //time_ofThorLoopControl=int(ComTimeForDefault);   //Bearbeitungszeit dieser Routine

                Serial.print(F("\tdt_ms:")); Serial.println(ComTimeForDefault);

                
               
                return iPower; 


}

//============================================================================================================================================================================================================================

void checkSerial1_for_KNX()
{
  //this routine checks 9600baud KNX Bus on Serial1
}

And here the code running on Mega2560

Code:
#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0xA8, 0x61, 0x0A, 0xAE, 0x2A, 0x10};
IPAddress ip(192, 168, 2, 185);
IPAddress myDns(192, 168, 2, 1);

EthernetClient client;

IPAddress server(192,168,2,11);

unsigned long lastConnectionTime = 0;           // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 5*1000;  // delay between updates, in milliseconds


int i=1;

void setup() 
{
  
  Ethernet.init(10);  // Most Arduino shields
  Serial.begin(115200);
  
    Ethernet.begin(mac, ip, myDns);
    Serial.print("My IP address: ");
    Serial.println(Ethernet.localIP());

     Ethernet.setRetransmissionCount(2);     //<------------------------------------------------------------------------------------------------------------------- 
     Ethernet.setRetransmissionTimeout(50);  //<------------------------------------------------------------------------------------------------------------------- 
  
    delay(1000);

    
}

void loop() 
{
 
    if (millis() - lastConnectionTime > postingInterval) 
    {
        for(int i=1; i<10; i++)
        {
          Request(i);
     
          delay(10);
        }
    }

}



// --------------------------------------

void Request(int i)
{
  unsigned long t1=millis();
  
  if (client.connect(server, 9010)) 
  {
     Serial.print("\nconnecting..."); Serial.print(i); 
     
     switch(i)
     {
        case 1: client.println("GET /PgEsN11"); break;
        case 2: client.println("GET /PgEsN22"); break;
        case 3: client.println("GET /PgEsN33"); break;
        case 4: client.println("GET /PgEsN44"); break;
        case 5: client.println("GET /PgEsN55"); break;
        case 6: client.println("GET /PgEsN66"); break;
        case 7: client.println("GET /PgEsN77"); break;
        case 8: client.println("GET /PgEsN88"); break;
        case 9: client.println("GET /PgEsN99"); break;
        
     }
     
     client.println();

     byte Wait=0; 
     while (client.available()<10 && Wait<25) {Wait++; delay(1);}

     Serial.print("\tWait:"); Serial.print(Wait); Serial.print("  "); Serial.print("got so far: "); Serial.print(client.available()); Serial.print("  ");

     if(client.available()==0)
     {
       Wait=0; 
       while (client.available()<10 && Wait<25) {Wait++; delay(1);}
       Serial.print("\textra wait:"); Serial.print(Wait); Serial.print("  "); Serial.print("after 25ms: "); Serial.print(client.available());
     }
     
     while(client.available()  ) 
     {
        char c = client.read(); Serial.write(c);
     }

     Serial.print("\tdt_ms:"); Serial.println(millis()-t1);
     
    
     client.stop();

     lastConnectionTime = millis();
  } 
  else 
  {
    Serial.println("connection #"); Serial.print(i); Serial.println(" failed");
  }

  
 
}
 
@Udo:
If you could post shorter code - together with a explanation how to use it with server or client on PC side) that demostrates the bug(s) it would be good.

However, why producing T4.1 over T4, if users cannot rely on its native Ethernet?
You might, if you think outside the box - see that ethernet is not used as much as you think :)

RAM usage: Sure, it's a 32BIT processor. An int consumes 2x the bytes. But it uses them much faster ;) And of course it's a difference to serve the whole ethernet library compared to an external chip that uses its own memory..
 
@Udo:
If you could post shorter code - together with a explanation how to use it with server or client on PC side) that demostrates the bug(s) it would be good.


You might, if you think outside the box - see that ethernet is not used as much as you think :)

RAM usage: Sure, it's a 32BIT processor. An int consumes 2x the bytes. But it uses them much faster ;) And of course it's a difference to serve the whole ethernet library compared to an external chip that uses its own memory..

Hi Frank, it is very straightforward: just load code 1 on a T4.1 and code 2 (for example) on a Mega. Nothing else is necessary. The fault happens even without using any other code. The Mega creates those connection requests, the T4.1 responds to it. With the commented out part - the EthernetClient part - most of my published T4.1 code is not even used. I left it in, in case somebody wanted to add EthernetClient requests too.

Does this answer your comment ?

Regards RAM usage, Due is equally a 32bit device (as you know), so I am aware of issues related to it, particularly as some of my applications collect lots of parameters. I only mentioned T4.1's RAM usage because it came initially as a surprise, but has not affected me.

In any case, my contribution here is at no means meant as criticism. It is merely a cry for help :) I want T4.1 to work for me :cool:

Furthermore, just for information, I am using wired Ethernet heavily, compared to WiFi, as Arduino's u-blox WiFi capable processors (or indeed their poorly performing former Wifi shield) do not keep a reliable connection, suitable enough for real-time control, particularly if you use a wider Mesh WLAN. A fact widely mentioned on their forum but unfortunately bitterly ignored. In addition to LAN, I use Serial and RF to connect devices.
 
Status
Not open for further replies.
Back
Top