Menu

Help to resolve measuring signal

Help
7 days ago
4 days ago
1 2 > >> (Page 1 of 2)
  • Alfredo Saetta

    Alfredo Saetta - 7 days ago

    Hello everyone. This is my first time programming in GCBASIC.
    I built a digital frequency display for an old tube-based amateur radio transceiver, the Drake TR-4C. The hardware is controlled by firmware I wrote, but I am having trouble with the formatted frequency display.
    The value is correct coming out of the frequency measurement and correction routines, but something goes wrong after executing the Str32() function. Str32() is used to convert the value of the FREQUENZA variable into the 10-character string variable FREQ_STRING.
    The three attached photos show:
    1-the correct value contained in the FREQUENZA variable;
    2-the value displayed after executing FREQ_STRING = Str32(FREQUENZA);
    3-the resulting corrupted formatted value.
    Does anyone have any idea why this is happening?
    I initially used a PIC16F648 and, thinking I might be hitting RAM limits, I migrated the project to the higher-capacity PIC16F1847, but the result remained exactly the same.
    The interesting point is that Str32() works correctly when used with constants, but produces this problem when the argument is the dynamically calculated Long variable FREQUENZA.

     
  • Anobium

    Anobium - 7 days ago

    Hello, We can resolve.

    Before I make any guess, please share your ASM file generated. This will tell me lots about your setup/versions.

    Anobium

     
  • Alfredo Saetta

    Alfredo Saetta - 7 days ago

    Thank you very much for your interest and for taking the time to investigate this issue. I really appreciate your help.

     
  • Anobium

    Anobium - 7 days ago

    Thank you. I know your build now and your setup

    Can you post your code?

     
  • Alfredo Saetta

    Alfredo Saetta - 7 days ago

    Certainly, here it is.

     
  • Anobium

    Anobium - 6 days ago

    Please use LongToString() this may resolve. I will check tomorrow if we have updated that function.

     
  • Anobium

    Anobium - 6 days ago

    You should add #option explicit to your program. This will highlight another issue. ♧

     
  • Alfredo Saetta

    Alfredo Saetta - 6 days ago

    Follow-up test results

    I also tried LongToString(FREQUENZA) as you suggested, but unfortunately it produces exactly the same incorrect result as Str32(FREQUENZA).

    I then performed some additional tests to try to isolate the problem.

    FREQUENZA is correct when it comes out of the MISURA_FREQUENZA routine, and it is not altered by Str32() or by LongToString() at that point. IF_REALE is also correct, and both Print IF_REALE and Str32(IF_REALE) work correctly.

    The problem appears when FREQUENZA is processed through CORREGGI_CALCOLA.

    I tested this step by step. With the 10-meter (10C, 10B, 10A) and 15-meter correction routines active, everything still works. When the 40-meter routine is added, the error appears. Removing any one of those routines makes the error disappear again.

    The same effect occurs with the PTO section: when enough conditional code and nested routine calls are added, the problem appears. This makes me wonder whether the problem may be related to the amount or structure of code generated by the compiler, rather than to the Str32() or LongToString() functions themselves.

    I also added #option explicit as you suggested. The compiler then reported only one undeclared item: CMCON, which was simply a leftover from the previous PIC16F648 version during the migration to the PIC16F1847. I replaced it with the appropriate ANSELA configuration, and the program then compiled without any other #option explicit errors.

    I hope these additional tests and the ASM/source code can help identify what is happening.

     
  • Anobium

    Anobium - 6 days ago

    Update: should be is resolved.

    After pulling the current version of string.h, Str32()/LongToString() now use a rewritten implementation (Do While SysValTemp > 0: Mod 10, /10 : Loop, reversing the digit string at the end) instead of the old chain of divisions by large constants (1,000,000,000 down to 10) through SYSDIVSUB32.

    • Compiles clean
    • Checked the generated .asm — FN_STR32 ( which is really LongToString) now only ever divides by the constant 10, so the old large-divisor path issue is no more

    You still need to confirm on the actual board, but the compile-time evidence lines up with what I suspected.

    The attachment goes in your C:\GCstudio\gcbasic\include\lowlevel folder.

     

    Last edit: Anobium 6 days ago
  • Alfredo Saetta

    Alfredo Saetta - 6 days ago

    I replaced string.h with the updated version you provided and recompiled the complete project. The code size decreased from about 41,9 % to 37,7%, so the new Str32()/LongToString() implementation is definitely being used. However, on the real 16F1847 target I still get exactly the same incorrect result.

     
  • Anobium

    Anobium - 6 days ago

    Ok. Write me a test program. Just the essential code to show the bug. Hard code values as I do not have the sensors etc. Just enough code so I can run here.

     
  • Alfredo Saetta

    Alfredo Saetta - 6 days ago

    I tried to reduce the program to a minimal test case, but the problem cannot be reproduced in the reduced version. Even with the simulated frequency calculation, the complete correction routines and the gestione_IF routine, LongToString() works correctly. The problem only appears in the full application.

     
  • Anobium

    Anobium - 6 days ago

    I need to values that i can test against. I need to hard code some values.
    Are there other values that need to be hard coded?

    RAW_FREQUENCY = ????
    FREQUENCY = ????
    

    ' =====================================================================
    ' FINAL FREQUENCY RECONSTRUCTION (DWORD / LONG)
    ' =====================================================================
    FREQUENCY = TIMER1 ' Read 16-bit value via #define
    TEMP_OV = OVERFLOWS * 65536 ' Sum accumulated overflows (65536 per full cycle)
    FREQUENCY = FREQUENCY + TEMP_OV
    FREQUENCY = (FREQUENCY * 125) / 10 ' Mathematical calculation based on gate and external prescaler /10
    RAW_FREQUENCY = FREQUENCY

    RAW_FREQUENCY =
    FREQUENCY =

    End Sub

     
  • Anobium

    Anobium - 6 days ago

    I hard code FREQUENCY = 4900002 and I get

    What should I get?

     

    Last edit: Anobium 6 days ago
  • Anobium

    Anobium - 6 days ago

    Struggling to understand the issue here.

    For a fixed FREQUENCY the number is calculated as 4101473 and the String of that is "4101473" and that on the LCD.

    Info put out via Serial port.

    Num: 4101473
    Str: 4101473
    Num: 4101473
    Str: 4101473

    And, see https://1drv.ms/v/c/2f87ffe77f3dbec7/IQDYt32KK5PlQ442tDSw5J8kAf0igCKPhFlXcB_IQ4IXrHs?e=avO9MU

     

    Last edit: Anobium 6 days ago
  • Alfredo Saetta

    Alfredo Saetta - 6 days ago

    I can see that your test uses a changing FREQUENCY value, but it is not generated by the MISURA_FREQUENZA calculation. In my case, the problematic value is produced at runtime by the Timer1 measurement routine on RB6/T1CKI. FREQUENZA is built from TIMER1 and OVERFLOWS, then multiplied/divided before entering CORREGGI_CALCOLA. A directly assigned or otherwise externally changing FREQUENCY does not reproduce the fault on my PIC16F1847.

     
    • Anobium

      Anobium - 6 days ago

      Would you agree this is not a LongToString issue?


      What is the input signal signal frequency and type?

       
  • Alfredo Saetta

    Alfredo Saetta - 6 days ago

    Yes, I agree; the problem isn't the STR32 function. The input signal is sinusoidal and is taken from the radio's mixer. Essentially, there is a VFO—which Drake calls a PTO—that generates a frequency; depending on the band switch position, this frequency is either added to or subtracted from the intermediate frequency (IF) value of 9,000,000 Hz. The PTO frequency ranges from 4,900,000 to 5,500,000 Hz. When the band switch is set to 80m, an optocoupler activates and pulls PIN_FOTO to logic low (zero); in this case, the software calculates FREQUENCY = 9,000,000 - PTO, resulting in a displayed frequency range of 3,500,000 to 4,100,000 Hz. For the 20m band, the optocoupler is off and PIN_FOTO goes to logic high (1); here, the software adds the IF to the PTO frequency, resulting in a displayed range of 13,900,000 to 14,500,000 Hz. For the other bands (15m, 40m, and 10m), local oscillators are used, from which both the PTO frequency and the intermediate frequency are subtracted. So, let's assume the radio is set to 80m and the frequency reading at Port B, Pin 6 is 5,100,000 Hz; the captured frequency value won't be exactly 5,100,000 Hz—it will differ slightly due to delays and so on. This captured value must first be corrected before being used in the calculation involving the intermediate frequency. And here the problem arises: if I read the FREQUENCY output from the frequency measurement routine, it is what I expect—for instance, if the input frequency at pin RB6 is 5,300,000, the value inside FREQUENCY is 5,301,600. This 1,600 Hz difference is subtracted when the signal enters the correggi_calcola (correct/calculate) routine, and then—depending on the value of PIN_FOTO—it is either subtracted from or added to the intermediate frequency. Therefore, the following calculation should take place inside the correggi_calcola routine:
    9,000,000 - (5,301,600 - 1,600) = 3,700,000 Hz
    However, the resulting value is 3,695,851 Hz. If I comment out the correction blocks (10a, 10b, and 10c) within the correggi_calcola routine, the frequency returns to the correct 3,700,000 Hz. I’ve gone into a bit of detail, but I had no other choice.
    I forgot to mention that, naturally, the frequency taken from the radio isn't applied directly to pin 6 of Port B; instead, it is first passed through a J310 FET buffer, then a 74HC14 Schmitt trigger wave-shaper, and finally a divide-by-10 circuit—so an input frequency of 5,300,000 Hz enters the PIC at 530,000 Hz.

     
  • Anobium

    Anobium - 5 days ago

    Thank you

    However, what is #define TIMER1 = TMR1L.Word meant to do?

     
  • Alfredo Saetta

    Alfredo Saetta - 5 days ago

    TIMER1 is simply an alias for the 16-bit Timer1 value (TMR1H:TMR1L). I use #define TIMER1 = TMR1L.Word so that FREQUENZA = TIMER1 reads the complete 16-bit Timer1 counter value in one operation.

     
  • Anobium

    Anobium - 5 days ago

    #define TIMER1 = TMR1L.Word does not do that. I am surprised it compiled. Remove it.

    TIMER1 is already an alias to TMR1H and TMR1L. See the Help.


    The issue must lay in the measure_frequency() method.
    Examine it carefully.
    Replace TEMP_OV = OVERFLOWS * 65536 with a ROTATE it will be a lot faster.

    I would look very carefully at T1CON.


    All I can do for today.

    Evan

     
  • Alfredo Saetta

    Alfredo Saetta - 5 days ago

    I followed your instructions: I removed #define TIMER1 = TMR1L.Word and corrected T1CON to T1CON = 0b10000101, but it still throws an error. The only thing left is to use ROTATE instead of TEMP_OV = OVERFLOWS * 65536, but I don't understand how to do that.
    Could you show me the exact GCBASIC syntax you mean for replacing TEMP_OV = OVERFLOWS * 65536 with ROTATE?

     
  • Anobium

    Anobium - 5 days ago

    What throws an error? A compiler message?

    You must use #option explicit


        //! TEMP_OV = OVERFLOWS * 65536         ' Add accumulated overflows (65536 for each full cycle)
    
        TEMP_OV = OVERFLOWS                 ' Widen a Long (0-extended)
        Repeat 16                           ' *65536 = shift left di 16 bit (piu' economico di una moltiplicazione Long)
            Set C Off
            Rotate TEMP_OV Left
        End Repeat
    
     

    Last edit: Anobium 5 days ago
  • Anobium

    Anobium - 5 days ago

    Just look at the code again.

    Not related to the measurement routine but a bug found.

    The 10a/10b/10c frequency windows overlap each other (37.5–37.6 MHz and 38.0–38.2 MHz are each claimed by two blocks). Since correggi_calcola uses independent Ifs rather than ElseIf, a raw reading in either overlap zone would run two correction subs back-to-back, subtracting IF_REALE twice and giving a badly wrong result. Worth tightening those boundaries (e.g. 37.6 exclusive lower bound on 10b) even though it's not what's hurting you right now.

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.