Announcement

Collapse
No announcement yet.

Limp/dead mode

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • tonton81
    replied
    here is the results, i just transfered the lcd code and library over to my project
    on the lcd screen if you see, most if not all icons are gone, by default they will show when lcd is powered up. this is to show the one shot trigger is working successfully.
    if you take a look closely you'll see it come on by default and blip off right away as the library issues the one shot trigger on a successful ACK response that appears after any NAK.

    As I move the iphone over to the tablet, I printed a few details to the monitor, at what millisecs before the mcu sent the one-shot update to the lcd when the lcd was ready.

    tablet shows:
    time of wakup ms
    time of lcd ready ms (ack response confirmed), and issue a one time update of icons, etc
    total time in between wake up to ready mode


    please turn down your speakers, i dont know why the iphone7plus?? is so sound sensitive lol

    https://www.youtube.com/watch?v=DtY_...ature=youtu.be

    Leave a comment:


  • tonton81
    replied
    We start with lcd on, then take a look at loop speed in realtime while sending tons of data to lcd, next we go ahead and pull the lcd power line, then goto the monitor to see what happens. the "timeout" is printed by the library during debugging, as you see, during this tineout, the main loop didnt do any random printing of digits to the serial monitor. this resulted in the whole loop being flatlined and unresponsive. as you see in the debugging, after the timeouts accumulated to the limit consecutively, the library shut itself off and there was no more genie processing being done, at all, and restored full functionality of the mcu, we didnt even need to disable any writeobjects or readobjects in your sketch, they are simply ignored until the library "wakes up". This is all inline and automatic and doesnt need you to implement extra code in your sketch either. I then go and connect the lcd, notice the loop is still running full speed while all genie reads or writes are ignored. the lcd will show no movement while loop still runs uninterrupted. Great. I setup a digitalRead as an example to trigger the library wakeup, once i grounded the pin, library woke up and immediately started showing data!

    https://www.youtube.com/watch?v=C4WA...ature=youtu.be

    the self-disable-library will look for consecutive timeouts, one after the next, if you had a timeout here or there that was just a glitch, no problem, the moment the link gets idle or a response without a timeout on next command, the counter is reset automatically, so unless it times out 20 times *in a row* it wont disable itself.

    Without this the library will do an internal timeout error stock 1sec interval, mod 100ms intervals, blocking, and your loop cycle will drop exponentially, if not creep to a total stop. This is a great solution if I ever need to take the lcd out for programming without having my project creep to a total stop because it's not connected.
    Last edited by tonton81; 25th February 2017, 09:59 AM.

    Leave a comment:


  • tonton81
    replied
    just added a new feature, full library "self & total disable" without needing to disable your sketch commands.
    this essentially counts to 100 consecutive timeouts, once the limit is reached, the library disables itself, no sketch code is necessary as it's self-automated.
    I have also created a new function to enable it, and it works great. new library command: genie.ENABLE();

    Code:
      if ( Event.reportObject.object == GENIE_NOSCREEN && Event.reportObject.index == GENIE_DISABLED ) {
        /*Genie disabled itself and prevents all read/write of objects.
           This gives the mcu full speed without doing any library work.
        */
        Serial.println("LCD DATA CUT OFF");
    during the timeouts the library runs at 100ms timeouts internally and can even lock up the loop function of the sketch. Now, the library is smart enough to say, "hey, 100 timeouts @ 100ms each, enough is enough, I'm shutting myself off and giving full cpu speed to micro, if you ever want me to continue, run genie.ENABLE(); <-- library function);

    in the sketch it'll be very easy to enable the lcd when power is supplied to the lcd

    Code:
    if ( digitalRead(mosfetPinExample) ) genie.ENABLE();
    // <---- this must be a one shot command after writing the pin high, this time when you go lcd-less one day (reconfiguration/testing), your mcu will take care of other things while not doing any genie work during runtime. Thats the only code you need in your sketch to wake up the library after it puts itself to sleep

    I will upload another video showing random serial.println(random(10,99)); in the loop cycle, to show how it's functioning, I will debug the output in the status window, you will see as the timeouts cause the loop to drag up until the library shuts itself off, then watch the teensy go full speed on the monitor, and as i power off and on lcd by code, watch it return to normal state.

    Leave a comment:


  • tonton81
    replied
    here is a demonstration of it in action on the test bench:

    Bench Test Sketch:

    Code:
    #include <genieArduino.h>
    Genie genie;
    
    int LCD1Form = 1;
    bool lockValue;
    uint32_t lockValueT;
    
    void setup() {
      Serial.begin(200000);
      Serial1.begin(625000);
      genie.Begin(Serial1);
      genie.AttachEventHandler(myGenieEventHandler);
    }
    
    void loop() {
      genie.DoEvents();
      genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 399, random(111, 999));
      if ( lockValue && millis() - lockValueT >= 2000 ) lockValue = 0;
      if ( LCD1Form == 1 ) {
        if ( !lockValue ) {  /// we lock these fields to demonstrate a successful recovery single shot init, then return to normal.
          genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 0, random(111, 999));
          genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 1, random(1111, 9999));
        }
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 0, random(100, 120));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 1, random(100, 120));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 2, random(40, 60));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 3, random(40, 60));
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 4, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 4, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 5, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 5, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 6, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 6, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 7, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 7, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 8, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 8, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 9, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 9, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 10, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 10, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 11, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 11, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 12, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 12, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 13, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 13, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 14, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 14, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 15, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 15, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 16, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 16, 0xFFFF);
      }
    }
    
    void myGenieEventHandler(void) {
      genieFrame Event;
      genie.DequeueEvent(&Event);
      if ( Event.reportObject.object == GENIE_OBJ_FORM ) LCD1Form = genie.GetEventData(&Event);
      if ( Event.reportObject.object == GENIE_ACK && Event.reportObject.index == GENIE_READY ) {
        Serial.println("LCD Detected in ready state! Show 2 locked digits for 2 seconds to demonstrate functionality...");
        Serial.println("Remember, this is set once and once only until a full power cycle or a complete buffer corruption recovery");
        lockValueT = millis();
        lockValue = 1;
        genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 0, 555);
        genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 1, 5555);
        genie.ReadObject(GENIE_OBJ_FORM, 0); // <-- this commands the lcd to say what form it's on, to keep selective updates on the right form.
      }
    }
    https://www.youtube.com/watch?v=TQsb...ature=youtu.be

    First testing stage, full power off and on of the lcd (3x test) (Time of test 0:00 -> 0:27)
    Second testing stage: LCD's RX line, hot plugging ( ~ 25x test) (Time of test 0:27 -> 0:50)
    Third testing stage: LCD's TX line, hot plugging ( ~ 10x test) (Time of test 0:50 -> 1:13)
    Forth testing stage: full power off and on of the lcd (1x test) (Time of test 1:13 -> 1:29)
    Fifth testing stage: full power off and on of teensy 3.5 (3x test) (Time of test 1:30 -> 1:58)
    Last edited by tonton81; 25th February 2017, 12:59 AM.

    Leave a comment:


  • tonton81
    replied
    Code:
    #include <genieArduino.h>
    Genie genie;
    
    int LCD1Form = 1;
    
    void setup() {
      Serial.begin(200000);
      Serial1.begin(625000);
      genie.Begin(Serial1);
      genie.AttachEventHandler(myGenieEventHandler);
    }
    
    void loop() {
      genie.DoEvents();
      if ( LCD1Form == 1 ) {
        genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 0, random(111, 999));
        genie.WriteObject(GENIE_OBJ_CUSTOM_DIGITS, 1, random(1111, 9999));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 0, random(100, 120));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 1, random(100, 120));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 2, random(40, 60));
        genie.WriteObject(GENIE_OBJ_USERIMAGES, 3, random(40, 60));
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 4, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 4, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 5, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 5, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 6, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 6, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 7, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 7, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 8, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 8, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 9, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 9, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 10, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 10, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 11, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 11, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 12, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 12, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 13, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 13, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 14, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 14, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 15, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 15, 0xFFFF);
        random(0, 2) ? genie.WriteObject(GENIE_OBJ_USERIMAGES, 16, 0) : genie.WriteObject(GENIE_OBJ_USERIMAGES, 16, 0xFFFF);
      }
    }
    
    void myGenieEventHandler(void) {
      genieFrame Event;
      genie.DequeueEvent(&Event);
      if ( Event.reportObject.object == GENIE_OBJ_FORM ) LCD1Form = genie.GetEventData(&Event);
      if ( Event.reportObject.object == GENIE_ACK && Event.reportObject.index == GENIE_ACK ) {
        Serial.println("LCD Detected in ready state!");
        genie.ReadObject(GENIE_OBJ_FORM, 0);
      }
      if ( Event.reportObject.object == GENIE_NAK && Event.reportObject.index == GENIE_NAK ) {
        // set variables here, not necessary.
      }
    }
    I just added the ability to the library to report ack's and nak;s since they wernt implemented, this is beneficial for me as, besides live streaming data always, there are some things on screen that is not always updated realtime, but only when they change. That means everytime to screen turns on, some icons are set, others not. Comparing state prevents unnessary writes to the display essentially make it perform faster, however, a drawback, you have to force update it on next power up. I needed a way to achieve "ready" state after power up as previously I used millis() with about 1.2sec before it updates all gauge icons to current state. Now that I added the one-shot ACK ability on power up, I am able to update those icons as soon as the lcd is "ready" and communicating. I have tried many times to "crash" it for tests, but unless your writing to non existant objects, I can't make it crash at all. (full power, hot plugging tx/rx lines, mid resetting it during runtime). all at 625K baud. I am running 325K in car due to the 6 foot 22 gauge cabling, hasnt hiccuped at all and running day and night ( i rarely sleep )

    This week during my tests, I've used a nak counter of 100, which reports ~ 20 NAKS during power up, and, wait for it, then comes the ONE ACK right after, as a confirmation that the lcd is ready for any and all inputs.
    Last edited by tonton81; 24th February 2017, 08:54 AM.

    Leave a comment:


  • tonton81
    commented on 's reply
    yes if i sent a bad request it would clear the buffer which is why a counter would be preferable (maybe 999 naks == reinitialize com), but it does prevent the endless nak loop the display gets in that would otherwise require the reset trigger, but then you'd need to make the library monitor the naks like im doing now in order to initialize the gpio reset line which would still clear the lcd buffer making it resume, except that reboots the lcd back to original form, nak recover continues current form

  • ESPsupport
    replied
    I couldn't recommend that as a solution as it breaks the #1 rule of a master - slave relationship, and that's that the slave should not do anything other than what it's told to do.

    Whilst it may work for your particular situation, it's quite possible that it could create a virtual deadlock situation where the master is trying to get the slave reset but the slave keeps detecting a NAK situation and throwing away the data from the master.

    Leave a comment:


  • tonton81
    replied
    the above sample i worked on today never freezes, i was able to replicate the problem using higher baud and hammering the uart while debugging the library which led me to this solution, so it definately will work at lower baud rates as well.
    as a proof of concept, I rolled back the original P5.inc to demonstrate the behaviour which shows that only, at this current baud rate (625k) with full speed objectwrites only a reset pulse, or a couple of power cycles on the lcd will get it back up and running, followed by a feedback from the library debugging at the end.

    These issues were barely seen at 200k baud normally, quite intermittant, but im glad i was able to replicate it very easy in order to find a solution to a lockout

    https://www.youtube.com/watch?v=smrN...ature=youtu.be

    the serial monitor at the end shows the lcd is returning constant nacks for all valid writeobjects from teensy, however, reinitializing the com on the lcd on this type of failure (NAK section) shows the above posts as working flawlessly, every time, shall the buffer get out of sync or overflowed, it can be recovered without interrupting the host
    Last edited by tonton81; 20th February 2017, 12:58 PM.

    Leave a comment:


  • tonton81
    replied
    first stage of video is depowering and repowering the teensy, the second stage of the video is a full power cycle of the lcd
    result: no lockups, streaming data, at 625k baud
    and damn, that teensy boots fast

    https://www.youtube.com/watch?v=2kn3...ature=youtu.be
    Last edited by tonton81; 20th February 2017, 11:42 AM.

    Leave a comment:


  • tonton81
    replied
    hey guys, ive been playing internally in the ide code finding an issue, been having for a bit of time with that, but i finally found it

    there is an issue where, not for most people, but it can happen, that the lcd locks. it does not seem to happen when there is less data going towards the lcd. I have been debugging the genie library, the source was not of the arduino core/genie library, but a repetitive NAK response, even for valid commands, which led me tonight to dig deeper into the issue.

    I've converted my genie code to visi just to get an idea of what the com variables are and implemented in the P5.inc sketch a routine for 2 areas:

    Code:
                    >?IElif1?< if (   (cmd[0] == READ_OBJ)
                             && (cmdi == 4)         )
                        if (InputCS)
                            nak0() ;
                        else
                            ReadObject(cmd[1], cmd[2]) ;
                        endif
                        cmdi := 0 ;
                    else if (   (cmd[0] == WRITE_OBJ)    // 6 byte write command (gen option)
                             && (cmdi == 6)          )
                        if (InputCS)
    com_Reset();
    com_Init(comRX,CMDLenMAX,0);
    com_SetBaud(COM0,60000);
    com_TXbuffer(comTX, 100, 0);
                            nak0() ;
                        else
                            WriteObject(cmd[1], cmd[2], cmd[3] << 8 + cmd[4]) ;
                            >?seroutx?<(ACK) ;
                        endif
                        cmdi := 0 ;
                    else if (   (cmd[0] == WRITE_CONTRAST)
                             && (cmdi == 3)         )
                        if (InputCS)
                            nak0() ;
                        else
                            gfx_Contrast(cmd[1]) ;
                            >?seroutx?<(ACK) ;
                        endif
                        cmdi := 0 ;
                    else if (cmdi == 6)    // we have 6 bytes and we've gotten here -> something wrong
    com_Reset();
    com_Init(comRX,CMDLenMAX,0);
    com_SetBaud(COM0,60000);
    com_TXbuffer(comTX, 100, 0);
                        nak0() ;
                        cmdi := 0 ;
                    endif
    this solution is currently working non-stop plugging in and unplugging the lcd from the micro, be it lcd power, or mcu power, either process, the data immediately continues without hessitation. I will post a video soon of this in action. This issue I have not found before when I made the genie code work because it wasn't doing high speed data like I am doing now. This solution works by resetting and reconfiguring the com port of the lcd as soon as an NAK is about to be sent back to the arduino/teensy for processing. Granted, a solution like this essentially is the same as wiping out the buffer on the lcd, where in some cases NAK's would be useful? I would doubt it, unless there was a baud error that tripped it to flush all buffers.

    I was wondering, since this solution prevents the LCD from ever locking up (and I spent all day&night verifying this) perhaps there is a way to include a NAK counter with this solution, and if the NAK's exceed a certain limit (25?) to issue a full com reset & initialization? or should I keep it like this?

    Code:
    com_Reset();
    com_Init(comRX,CMDLenMAX,0);
    com_SetBaud(COM0,60000);
    com_TXbuffer(comTX, 100, 0);
    attached is a solution to prevent the lcd from ever locking up during runtime, i will provide the video in a few minutes
    Attached Files
    Last edited by tonton81; 20th February 2017, 11:22 AM.

    Leave a comment:


  • tonton81
    replied
    55 lines canbus streaming @ 200,000 baud
    on the next lcd update i will be boosting the baud to 600,000 so we can sample the difference using the canbus streaming forms


    Leave a comment:


  • tonton81
    replied
    here is the video i made with a remote start arm shutting lcd off and then pressing brake pedal to release remote starter which then opens lcd.
    as you can see the data starts streaming fine

    Last edited by tonton81; 12th January 2017, 05:34 AM.

    Leave a comment:


  • tonton81
    replied
    just for an update, the function i ended up not using as it was already implemented in the library mod i did, at home i did the tests with my modded library but forgot to put it on my tablet for the carpc so i was basically running stock library *facepalm* anyways, the library is the same update on page 2 of this thread, except all millis() timers in the library are changed to unsigned long. no need to implement the extra function posted above as the library will handle timeouts as purges. the data that transmits to the lcd doesnt go limp, and i can full power on & off at will without any extra sketch code

    Leave a comment:


  • tonton81
    replied
    Click image for larger version  Name:	IMG_0033[1].JPG Views:	1 Size:	3.83 MB ID:	55382

    well finally got the 2 lcds in the panel, too cold for painting so that'll wait for summer LOL
    anyways, i will be able to better test the functionality of the library.
    What I've experienced so far in the code:

    I've had extra port expander pins available near the cluster, so I decided to tap 2 reset lines even though i wont use them, but for "what if" scenarios. They are default pulled HIGH since the LCDs reset on active LOW.

    Data FROM LCD to MCU is okay on a full power cycle, however, sending data from what I've seen with the screen missing (OFF actually) like from the canbus traffic (for gauges testing at the moment), The limp mode would return This explains why the calculator demo worked, as it's an INPUT trigger. I, have however ressolved this issue in the library, there seems to be a function (that needs testing?) according to the library. It's a private function, since it's unused, I moved it to public so I may have access to it in my sketch. I also noticed some long millis() timers that should be unsigned long, I have corrected those as well.

    The procedure is as follows now with the libraries's current mod:

    I turn off the LCD (during canbus data logging) via N-mosfet
    I turn on the LCD using gpio with mosfet, the lcd boots up,estimate the time you need for the LCD to boot up to your graphics (example, 3 seconds)
    I created a millis() variable which counts to 3 seconds before it initiates Screen1.Resync(); (during this time, or when lcd is off, mcu loop in unaffected).
    The data from the canbus streams suddenly start flowing to the LCD at that point, without any need of cycling the mcu or stopping it's program.

    This is the current status of my project while testing the library mods, I will have to find a bit of time to throw some graphics together and show some samples. currently the 2 lcds turn fully off and fully on via an arm/disarm of the alarm system, and the 4.3" contains a digital start which actually works great. I dont even need to jump in the car in the snow to start it, just disarm, (lcd turns on) open door, push button on lcd and it starts. more time to shovel
    Last edited by tonton81; 11th January 2017, 07:59 AM.

    Leave a comment:


  • tonton81
    replied
    Welp, I ripped out my OE cluster, desoldered the mini lcd, and put a ribbon cable on it, made the old cluster low profile to stay in the dash behind the lcd bezels. I am putting two 4D lcds, uLCD-43PT and uLCD70DT in this specific bezel, and the relocated OE lcd will be moulded to the top of the same bezel, sorta like a pod. Everything will be fiberglass filled
    Attached Files

    Leave a comment:

Working...
X