Announcement

Collapse
No announcement yet.

Limp/dead mode

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

  • #31
    For anyone interested, I finished fiberglassing the center portion of my dash with a 13.2" tablet, except for the exagerated size, it kinda looks OEM lol.., and soon going to be transferring the uLCD-70DT to the cluster, so fun stuff this fiberglassing

    Anyways, Here are 2 pics of the cable I have made and tested as per this thread discussion, all resisters are of course, 10K ohm, 3 wire to arduino, 2 wires to power source (this is presumed your arduino and power source have grounds already shared, in my case, the automotive field).

    Now you are able to turn on and off the LCD completely just by setting a digitalWrite HIGH(LCD OFF) or LOW(LCD ON) to it, without hindering the loop cycle speed of your microcontroller.
    This also deactivates the touchscreen as all lcd power is cut off, beneficial since false touches can be done if contrast was 0 (sleep mode)., also note, previously it was recommended to send the contrast level at a value once only,, which required more code and state machine. Now, just set it high or low in the loop, endlessly, this works fine and saves resources
    When powered back up, LCD will load it's default form obviously, you could use that as a splash page for your project, and have the form switch by microcontroller or by timer
    If your writing data to the first form immediately after powerup, you will see the data right away

    This cable has been tested using calculator demo without reset line or delays at 200000 baud, if you check, there is no reset line on the header
    For those who are curious, there will be a uUSB-PA5 programmer cable heatshrinked and sitting sparingly behind lcd, for the need to reprogram shall the need arise

    The ability to hot-plug gives us the capability to turn the lcd completely on or off without reloading the microcontroller (and create splash screens), for maximum energy saving and syncronized recovery
    Thanks
    Tony
    Attached Files
    Last edited by tonton81; 2nd November 2016, 07:23 AM.

    Comment


    • #32
      I went to take some quick pics just now, ill be painting them once the clusters are done
      Attached Files

      Comment


      • #33
        last pic for now
        Attached Files

        Comment


        • #34
          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

          Comment


          • #35
            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, 08:59 AM.

            Comment


            • #36
              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

              Comment


              • #37
                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, 06:34 AM.

                Comment


                • #38
                  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


                  Comment


                  • #39
                    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, 12:22 PM.

                    Comment


                    • #40
                      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, 12:42 PM.

                      Comment


                      • #41
                        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, 01:58 PM.

                        Comment


                        • #42
                          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.
                          Mark

                          Comment


                          • tonton81
                            tonton81 commented
                            Editing a comment
                            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

                        • #43
                          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, 09:54 AM.

                          Comment


                          • #44
                            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, 01:59 AM.

                            Comment


                            • #45
                              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.

                              Comment

                              Working...
                              X