Author Topic: Stymied: Why are my data sometimes doubled?[SOLVED]  (Read 2183 times)

0 Members and 1 Guest are viewing this topic.

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Stymied: Why are my data sometimes doubled?[SOLVED]
« on: November 04, 2023, 11:33:39 am »
1919082-0Project is reading an older (1990's) Mitutoyo magnetic scale with SPC output.
MCU: PIC16F1829 at 8 MHz.
Language: Microchip (MPLab) MPASM.  Snippet of the pertinent part of code (attached).  Note, readings are stored in registers d1....d13.
They are in consecutive registers in Bank 7 (big endian) to reduce the need for bank changes.  Bit order in each 4-bit "byte" is reversed, i.e., b'0001' is 0x08, which is fairly common practice.  Hence, I rotate receiving register right and swap nybbles to put the BCD data in the lowest nybble.

Attachments:
1) Assembly code
2) Datasheet for reading the output.  It is 52 bits presented as 13, 4-bit nybbles.
3) Schematic
4) O'scope with slow scan.
5) O'scope with faster scan showing 1's.  I read the data on the down slope of the clock.

Here's the problem.  Reads go fine; however, my results are usually double what the DRO on the Mitutoyo shows.  Looks like a rotation problem, right?  Unfortunately, that is not always the case.  The first couple of reads at the same sensor setting during hardware simulation show the correct value, such as 0.1140.  I can repeat that 2 or 3 times, but then it becomes 0.2280 and stays that way.  The read value changes appropriately with movement of the scale but remains double.  A release version of the code also gives double values, but it is impossible to know what the first 2 readings were.  Of course, any value larger than d.4 gets corrupted as the ASCII-based printing routine  is limited to 0...9 for each digit.  The first 4 "bytes" read all F, i.e., 0x0F consistently.    I have tried running the MCU at lower and higher speeds from 500 kHz to 32 MHz without changing the behavior; although, it seems higher speeds >8 MHz may skip the first few correct reads.  That latter observation is not easily reproduced.


The !REQ signal is inverted by the N-mosfet.  So, high on the scope (magenta trace) is actually pulling that input low on the sensor.  I have tried running the mCU at lower and higher speeds from 500 kHz to 32 MHz without effect

Any ideas of where the problem is?

EDIT: Before anyone screams, the attachments are screwed up.  They showed fine before posting.  I am working on it.  Update: All the intended attachments are there,  the Mitutoyo datasheet is a little corrupted.  And now, the order is not as shown in the body of my post.  I don't know how to change that without deleting and starting all over.
EDIT2:  The first of the Mitutoyo datasheet attachments seems to be corrupted.  So, I deleted it.  The second has 2 copies of the same page.  I don't know why, but it is probably better to leave it than try to fix it.
« Last Edit: November 09, 2023, 05:20:04 pm by jpanhalt »
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: Stymied: Why are my data sometimes doubled?
« Reply #1 on: November 04, 2023, 12:35:53 pm »


Code: [Select]

list p=16f1829      ; list directive to define processor
#include <p16f1829.inc> ; processor specific variable definitions
     errorlevel -302,-305
     RADIX     DEC
     
    __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
    __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
;10/27/23 changed CLKOUTEN to off!
   
;                            _____
;                        VDD|     |VSS
;                    Req/RA5|     |RA0/ICSPDAT
;                 Clk_in/RA4|     |RA1/ICSPCLK
;              RST/!MCLR/RA3|     |RA2
;                        RC5|     |RC0/Ser_in
;                        RC4|     |RC1
;                        RC3|     |RC2/LED
;                        RC6|     |RB4                 ;/Ser_out
;                        RC7|     |RB5/USART RX
;               USART TX/RB7|_____|RB6
;
;Constants
RST       equ  3         ;PORTA
Clk_in    equ  4         ;PORTA
Req       equ  5         ;PORTA
Ser_out   equ  7         ;PORTB
Ser_in    equ  0         ;PORTC
LED       equ  2         ;PORTC

;flag0 definitions
;    flag0,0  set = rx in progress     

List
     cblock    0x20      ;0x20 thru 0x6F are GP RAM in  Bank0
     char                     ;used in BIN2ASCII     
     char_lo                  ;used in BIN2ASCII
     txbyte              ;input to Put232
     ;bit_ctrL                 ;counts 4-bit words (BCD) in 13-word (52-bit) received string
     ;bit_ctrH                 ;counts BCD words in 13-word received string
     endc

     cblock    0x3A0     ;bank 7 GP RAM
     d1                       ;read data
     d2                       ;read data
     d3                       ;read data
     d4                       ;read data
     ;NB: The first 4 "bytes" are 0xF and can be ignored
     d5                       ;read data, sign bit
     d6                       ;    "    ,MSD (BCD)
     d7                       ;    "    ,BCD
     d8                       ;    "    ,BCD
     d9                       ;    "    ,BCD
     d10                      ;    "    ,BCD
     d11                      ;    "    ,LSD (BCD)
     d12                      ;    "    ,decimal point
     d13                      ;    "    ,units (0x0=mm, 0x8=inch)
     endc

     cblock    0x70      ;beginning of common RAM
     bit_ctr         ;used in Put232 and ISR during data collection
     delayhi         ;used delay macro
     flag0               ;flags
     temp0               ;general purpose temporary reg
     endc

;<snipped>
           
IOCIF_init                    ;(IOCIF=INTCON,0) on positive edge of Mitutoyo clock (Clk_in)
     movlb     7              ;                                                 |B7
     bsf       IOCAN,Clk_in   ;RA4 negative edge                                |B7
     clrf      IOCAF          ;clear all IOC flags                              |B7
     clrf      INTCON         ;INTCON,IOCIE   ;enable IOC                       |B?

FSR0_init
     movlw     high(d1)       ;Mitutoyo little endian MSByte has lowest number  |B7     
     movwf     FSR0H          ;used same endian here                            |B7
     movlw     low(d1)        ;                                                 |B7
     movwf     FSR0L          ;                                                 |B7
     
Main
     movlw     low(d1)        ;initialize FSR0 for new data                     |B7
     movwf     FSR0L          ;
     movlb     2              ;                                                 |B2
     bsf       LATA,Req       ;request data (short !REQ to ground)              |B2
     btfss     INTCON,IOCIF   ;check for first clock bit                        |B?
     bra       $-1            ;                                                 |B?
     call      GetData        ;                                                 |B2
     call      ClrDisplay     ;                                                 |B7
     call      Printf         ;                                                 |B7
     call      ClrData        ;returns |B7                                      |B7
     bra       Main

GetData
     movlb     0              ;                                                 |B0
     lsrf      PORTC,w        ;move PORTC,Ser_in state to STATUS,0              |B0
     rrf       INDF0,f        ;reverse bit order
     movlb     7              ;                                                 |B7
     clrf      IOCAF          ;get ready to detect next bit                     |B7               
     decfsz    bit_ctr,f      ;Common RAM                                       |B7
     bra       Nextbit        ;continue reading current nubble                  |B7
;11/02 test nybble received, reset !REQ high
;     movlb     2              ;This location stops "Nextbit"
;     bcf       LATA,Req
;     movlb     7
;11/02 test done
     swapf     INDF0,f        ;4-bit nybble received, divide nybble by 16       |B7
     comf      INDF0,f        ;compensate for inversion                         |B7   
     movlw     0x3F           ;                                                 |B7
     andwf     INDF0,F        ;converts 0xF(BCD) to 0x(ASCII#)                  |B7 
     bsf       bit_ctr,2      ;refresh bit_ctr to d.4                           |B7
     incf      FSR0L,f        ;get next nybble of data                          |B7
     movlw     low(d13+1)     ;detect end of data                               |B7
     xorwf     FSR0L,w
     btfss     STATUS,2
;     subwf     FSR0L,w        ;                                                 |B7
;     btfss     STATUS,0       ;clear when incremented FSR0L > low(FSR0(d13))    |B7
     bra       Nextbit        ;get next 4-but byte                              |B7
     movlb     2              ;read done                                        |B2     
     bcf       LATA,Req       ;                                                 |B2
     movlb     7              ;                                                 |B7
     movlw     low(d1)        ;end of read, reset FSR0 for next read            |B7
     movwf     FSR0L          ;         "                                       |B7
     clrf      IOCAF          ;11/02 Should not make a difference               |B7
     return                   ;                                                 |B
7
Nextbit
     btfss     IOCAF,Clk_in   ;check clock flag for next bit                    |B7
     bra       $-1            ;keep checking                                    |B7
     bra       GetData        ;                                                 |B7

     END
« Last Edit: November 04, 2023, 12:39:54 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: jpanhalt

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: Stymied: Why are my data sometimes doubled?
« Reply #2 on: November 04, 2023, 12:44:29 pm »
You're holding REQ low for the entire nibble, you should release it after the first bit was received.



Where are you checking that first 4 nibbles were 0xF? You might go out of sync otherwise.

Also, why asm? PIC16F183xx are much newer and perform pretty nice in C.
« Last Edit: November 04, 2023, 12:54:59 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: jpanhalt

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #3 on: November 04, 2023, 01:28:33 pm »
1) Yes, that is what he datasheet says/implies, but it didn't work, either in code or by actually checking it on the oscilloscope with a release version. The clock stopped when I released the REQ.  A current datasheet for the same series, but those devices have added controls, says to release it before the last bit (attachment).  Doable but hard to do.  What I did was release it at the end of the last byte.  The last byte is irrelevant as it tells the processor whether dimensions are metric or imperial.  My sensor has that (imperial) as a setting and the last byte doesn't matter.  Given the way I capture the data, it is hard to see how the results would start to be doubled after the first few reads.  It seems to me that a double read, noise,etc. would lead to corruption of values, but not simply double values.  Despite that theory, I tried setting bit_count to 3 and 5 and only got corrupted results.  (With right shifts, too few rotations should double results.  I have focused on that section and just don't see how it can happen.  Maybe fresh eyes will help.).
2) Yes, I check the first 4 nubbles and they ar 0x0F (actually 0x3F for printing).
3) I code in Assembly because I like to be in control.  :)  I am too old to start learning C, and a math error like this is probably not related to whether the code is in ASM or C.
 

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #4 on: November 04, 2023, 01:30:16 pm »
Here is the code using code tags.  Maybe it is more readable.

Code: [Select]

list p=16f1829 ; list directive to define processor
#include <p16f1829.inc>  ; processor specific variable definitions
errorlevel -302,-305
RADIX DEC

__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
;10/27/23 changed CLKOUTEN to off! 

;                            _____   
;                        VDD|     |VSS 
;                    Req/RA5|     |RA0/ICSPDAT 
;                 Clk_in/RA4|     |RA1/ICSPCLK 
;              RST/!MCLR/RA3|     |RA2 
;                        RC5|     |RC0/Ser_in 
;                        RC4|     |RC1 
;                        RC3|     |RC2/LED 
;                        RC6|     |RB4                 ;/Ser_out 
;                        RC7|     |RB5/USART RX 
;               USART TX/RB7|_____|RB6 
;
;Constants
RST equ 3 ;PORTA
Clk_in equ 4 ;PORTA
Req equ 5 ;PORTA
Ser_out equ 7 ;PORTB
Ser_in equ 0 ;PORTC
LED equ 2 ;PORTC

;flag0 definitions
;    flag0,0  set = rx in progress       

List
cblock 0x20 ;0x20 thru 0x6F are GP RAM in  Bank0
char ;used in BIN2ASCII     
char_lo ;used in BIN2ASCII
txbyte ;input to Put232
;bit_ctrL                 ;counts 4-bit words (BCD) in 13-word (52-bit) received string
;bit_ctrH                 ;counts BCD words in 13-word received string 
endc

cblock 0x3A0 ;bank 7 GP RAM
d1 ;read data
d2 ;read data
d3 ;read data
d4 ;read data
;NB: The first 4 "bytes" are 0xF and can be ignored
d5 ;read data, sign bit
d6 ;    "    ,MSD (BCD)
d7 ;    "    ,BCD
d8 ;    "    ,BCD
d9 ;    "    ,BCD
d10 ;    "    ,BCD
d11 ;    "    ,LSD (BCD)
d12 ;    "    ,decimal point
d13 ;    "    ,units (0x0=mm, 0x8=inch)
endc

cblock 0x70 ;beginning of common RAM
bit_ctr ;used in Put232 and ISR during data collection
delayhi ;used delay macro
flag0 ;flags
temp0 ;general purpose temporary reg
endc

;<snipped>

IOCIF_init ;(IOCIF=INTCON,0) on positive edge of Mitutoyo clock (Clk_in)
movlb 7 ;                                                 |B7
bsf IOCAN,Clk_in ;RA4 negative edge                                |B7
clrf IOCAF ;clear all IOC flags                              |B7
clrf INTCON ;INTCON,IOCIE   ;enable IOC                       |B?

FSR0_init
movlw high(d1) ;Mitutoyo little endian MSByte has lowest number  |B7     
movwf FSR0H ;used same endian here                            |B7
movlw low(d1) ;                                                 |B7
movwf FSR0L ;                                                 |B7

Main
movlw low(d1) ;initialize FSR0 for new data                     |B7
movwf FSR0L ;
movlb 2 ;                                                 |B2
bsf LATA,Req ;request data (short !REQ to ground)              |B2
btfss INTCON,IOCIF ;check for first clock bit                        |B?
bra $-1 ;                                                 |B?
call GetData ;                                                 |B2
call ClrDisplay ;                                                 |B7
call Printf ;                                                 |B7
call ClrData ;returns |B7                                      |B7
bra Main

GetData
movlb 0 ;                                                 |B0
lsrf PORTC,w ;move PORTC,Ser_in state to STATUS,0              |B0
rrf INDF0,f ;reverse bit order
movlb 7 ;                                                 |B7
clrf IOCAF ;get ready to detect next bit                     |B7               
decfsz bit_ctr,f ;Common RAM                                       |B7
bra Nextbit ;continue reading current nubble                  |B7
;11/02 test nybble received, reset !REQ high 
;     movlb     2              ;This location stops "Nextbit" 
;     bcf       LATA,Req 
;     movlb     7
;11/02 test done
swapf INDF0,f ;4-bit nybble received, divide nybble by 16       |B7
comf INDF0,f ;compensate for inversion                         |B7   
movlw 0x3F ;                                                 |B7
andwf INDF0,F ;converts 0xF(BCD) to 0x(ASCII#)                  |B7 
bsf bit_ctr,2 ;refresh bit_ctr to d.4                           |B7
incf FSR0L,f ;get next nybble of data                          |B7
movlw low(d13+1) ;detect end of data                               |B7
xorwf FSR0L,w
btfss STATUS,2
;     subwf     FSR0L,w        ;                                                 |B7   
;     btfss     STATUS,0       ;clear when incremented FSR0L > low(FSR0(d13))    |B7 
bra Nextbit ;get next 4-but byte                              |B7
movlb 2 ;read done                                        |B2     
bcf LATA,Req ;                                                 |B2
movlb 7 ;                                                 |B7
movlw low(d1) ;end of read, reset FSR0 for next read            |B7
movwf FSR0L ;         "                                       |B7
clrf IOCAF ;11/02 Should not make a difference               |B7
return ;                                                 |B7
Nextbit
btfss IOCAF,Clk_in ;check clock flag for next bit                    |B7
bra $-1 ;keep checking                                    |B7
bra GetData ;                                                 |B7

END
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: Stymied: Why are my data sometimes doubled?
« Reply #5 on: November 04, 2023, 01:35:37 pm »
Maybe it's not doubled, but shifted by 1 bit?
0.1140 would be  0000 0001 0001 0100 0000.
If you miss a clock bit, you'll get 0000 0010 0010 1000 0000 (0.228).

Make proper code, count the bits, add timeout countdown, wait of the first 4 sync nibbles (F F F F) .
You read the data in the clock faling edge, so  release REQ in that exact moment, in last bit.
No need to wait for clck rising? Anyways REQ doesn't seem the problem here.
« Last Edit: November 04, 2023, 01:47:13 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: jpanhalt

Online Andy Watson

  • Super Contributor
  • ***
  • Posts: 2162
Re: Stymied: Why are my data sometimes doubled?
« Reply #6 on: November 04, 2023, 02:05:04 pm »
The !REQ signal is inverted by the N-mosfet.  So, high on the scope (magenta trace) is actually pulling that input low on the sensor.
Is it ?

Probably just a typo but Q1 is drawn wrongly on the diagram - are we to assume that it has been wired correctly? Have you put the scope on the actual REQ pin? Seems a little odd that guage does not respond to the datasheet as per the REQ function.
 
The following users thanked this post: jpanhalt

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #7 on: November 04, 2023, 02:10:38 pm »
I will try that counting the whole string to see if there is a lost bit early on.

A left shift with an input, such as, 1111,1111,1111,1111,xxxx,0001,0001,0010,1001,etc. would give a bunch of doubles as expected plus some odd values (i.e., an increase by 1 in preceding bytes) preceding the 9's.

I had just pulled the proto board out to change the CD4069 to an Schmitt inverter (e.g, 74xx14) as shown in some of the Mitutoyo datasheets. 

Will post a follow-up.  After that is done.

John

 
 

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #8 on: November 04, 2023, 02:15:43 pm »
Yes, the FDV303 is shown incorrectly, but wired correctly.  There might be more modern devices available, but I started using it in 2008 or so.  I will have see what happened with my  EAGLE.  EDIT: I simply grabbed the wrong symbol (FDN360P) without reading the description carefully.  It is now fixed in my schematic. Thanks,
« Last Edit: November 04, 2023, 02:25:09 pm by jpanhalt »
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: Stymied: Why are my data sometimes doubled?
« Reply #9 on: November 04, 2023, 02:34:32 pm »
If Tck is ~500us, setup Timer2 so it overflows in 2ms.
Always check for overflow when waiting for clock.
On overflow, release REQ, wait another 2ms before retrying.
If clock is detected during waiting, reset timer counter (Reload the 2ms waiting), only restart when idling.

Why do you need the buffers? It's a very slow signal, no need for that?
Neither need to invert the clock or data signal, use IOCAP instead IOCAN.
Or use the SPI peripheral to receive the 13 bytes.

Same for REQ. You can do it by toggling the GPIO between input (HI-Z) or output set to low.
Set LATA=0, then simply bcf/bsf TRISA0 bit.
« Last Edit: November 04, 2023, 02:45:56 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: jpanhalt

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #10 on: November 04, 2023, 03:45:02 pm »
I am leaning toward a clock issue based on the attachment.  Code clearly releases REQ after the last byte, but the clock has 2 more beats.  Total beats for the read period are sill just 52.


I need to work on that.  Maybe forget about capturing byte 13.  Thus, the statement about releasing REQ before the last bit would be fulfilled. 

As for buffers, that's what Mitutoyo recommends. I added the two extra resistors to the inputs of the inverter to make proper LPF's, which are not shown in my schematic.  It made no difference.
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6537
  • Country: es
Re: Stymied: Why are my data sometimes doubled?
« Reply #11 on: November 04, 2023, 07:19:48 pm »
Also keep it simple, why are you storing variables in different banks without needing so? It only adds bank switching mess.
Did a bit of work, though incomplete, I think it will work better, follow program flow.
You still need to implement timer2 init, DecimalPoint, MeasureUnit, and probably other fixes.
All BANKSEL should be checked out. I have not taken extreme care of all bank switching.
But shows the idea, and the way to avoid unwanted/undefined behavior.
Code: [Select]
    List
    cblock    0x20              ;0x20 thru 0x6F are GP RAM in  Bank0
    timeout
    bit_count
    data_count       
    d5                          ;read data, sign bit
    d6                          ;    "    ,MSD (BCD)
    d7                          ;    "    ,BCD
    d8                          ;    "    ,BCD
    d9                          ;    "    ,BCD
    d10                         ;    "    ,BCD
    d11                         ;    "    ,LSD (BCD)
    d12                         ;    "    ,decimal point
    d13                         ;    "    ,units (0x0=mm, 0x8=inch)
    endc

     
IOCIF_init                      ;(IOCIF=INTCON,0) on positive edge of Mitutoyo clock (Clk_in)
    BANKSEL  IOCAN              ;
    bsf      IOCAN,Clk_in       ;RA4 negative edge                                |B7
    clrf     IOCAF              ;clear all IOC flags                              |B7
    clrf     INTCON             ;INTCON,IOCIE   ;enable IOC                       |B?

FSR0_init
    movlw    high(d5)           ;Mitutoyo little endian MSByte has lowest number  |B7     
    movwf    FSR0H              ;used same endian here                            |B7
    movlw    low(d5)            ;                                                 |B7
    movwf    FSR0L              ;                                                 |B7
     
Main
    movlw    low(d5)            ;initialize FSR0 for new data                     |B7
    movwf    FSR0L              ;
    BANKSEL  LATA               ;
    bsf      LATA,Req           ;request data (short !REQ to ground)              |B2
    call     GetData            ;                                                 |B2
    btfsc    timeout,1          ;Check if timeout ocurred
    bra      Timeout   
    call     ClrDisplay         ;                                                 |B7
    call     Printf             ;                                                 |B7
    call     ClrData            ;returns                                          |B7
    bra      Main

GetData
    movlw    8                  ;init values
    movwf    bit_count
    movlw    13
    clrf     data_count
   
GetNibble
    call     GetClk             ;Wait for clock
    btfsc    timeout,1          ;Check if timeout ocurred
    return                      ;Timeout ocurred
    movfw    PORTC              ;Read PORTC
    iorwf    INDF0,f            ;OR value with current nibble data
    decfsz   bit_count,f        ;Check if nibble is done
    bra      GotNibble          ;Done
    rrf      INDF0,f            ;Not done. Rotate right, make room for next bit (Data is stored in the 4 MSB)
    bra      GetNibble          ;Continue   
ParseNibble
    swapf    INDF0,flag         ;Swap nibbles
    movlw    10                 ;Subtract 10
    subwf    data_count,w       ;To the data count
    btfsc    STATUS,C           ;Check for carry bit (If set, we already received more than 4 nibbles, not header)
    bra      Check_header       ;Less than 5 bytes received, check for good header   
    movlw    9                  ;This is not header, subtract 9
    subwf    data_count,w       ;To the data count
    btfss    STATUS,Z           ;Check for zero bit
    bra      CheckData          ;Not sign data, skip
    movlw    0x20               ;This is d5, Sign data. Load ASCII "Space" into w
    addwf    INDF0,f            ;Add to sign data (Convert to space, or later to '-' symbol)
    movlw    0                  ;Preload w with 0 for the next step
    btfsc    INDF0,0            ;Check for sign LSB (Now it would be 0x21)
    movlw    0xC                ;Override w with 0xC, convert to '-' symbol by adding 0xC (0=x21->0x2D)
    addwf    INF0,f             ;Update symbol data   
    bra      Nibble_OK          ;Done
CheckData
    movlw    2                  ;Subtract 2
    subwf    data_count,w       ;To the data count
    btfsc    STATUS,C           ;Check for carry bit (If set, we already received more than 4 digits)
    bra      DecimaPoint        ;This is decimal point
    movlw    1                  ;Subtract 1
    subwf    data_count,w       ;To the data count
    btfsc    STATUS,C           ;Check for carry bit (If set, we already received more than 4 digits)
    bra      MeasureUnit   
   
DecimalPoint
    ;blah blah
     bra      ParseDone          ;Done
MeasureUnit
    ;blah blah
     bra      ParseDone          ;Done
   
    movlw    0x30               ;Add 0x30
    addwf    INF0,f             ;To current data, to convert to ASCII       
Nibble_OK
    incf     FSR0L,f            ;point to next data
    bra      ParseDone          ;Done
Check_header
    movlw    0xF                ;Subtract 0xF                             <--- For non-inverted data input.
    subwf    INDF0,w            ;From current nibble                      <--- For non-inverted data input.
    movfw    INDF0              ;Read nibble                              <--- For inverted data input.
    btfss    STATUS,Z           ;check for zero bit (We should have received 0xF, header nibble)
    bra      Nibble_OK          ;OK, Receive next nibble
    call     SetTimeout         ;Bad header data, trigger a timeout
    return                      ;Return to main
GotNibble
    bra      ParseNibble
ParseDone
    decfsz   data_count,f       ;Decrease data count, got all 13 nibbles?
    bra      NextNibble         ;No, continue
    movlb    0                  ;Yes
    return                      ;
   
GetClk
    clrf     IOCAF              ;Get ready to detect next bit                     |B7       
    clrf     TMR2,f             ;Clear the counter
    clrf     timeout,f          ;Clear the timeout flag
    bcf      PIR,TMR2IF         ;Clear timer flag
    btfsc    IOCAF, Clk_in      ;check clock flag for next bit                    |B7
    return                      ;Got bit
    btfss    PIR,TMR2IF         ;Check for timer overflow (Timeout)                               
    bra      GetClk             ;No timeout, keep waiting
SetTimeout
    bsf      timeout,1          ;Set timeout flag
    return                      ;Timeout ocurred
   
Timeout
    BANKSEL  LATA               ;
    bcf      LATA,Req           ;Release request data
    BANKSEL  TMR2               ;
    clrf     TMR2,f             ;Clear the counter
    bcf      PIR,TMR2IF         ;Clear timer flag
Timeout_wait
    btfsc    PIR,TMR2IF         ;Check for timer overflow (Timeout)
    bra      Main               ;Timeout done, restart
    btfss    IOCAF, Clk_in      ;Not done, check if clock flag is set
    bra      Timeout_wait       ;Clock flag not set, keep waiting
    clrf     TMR2,f             ;Got clock signal! Clear the counter (Reset the timeout wait)
    bcf      PIR,TMR2IF         ;Clear timer flag
    clrf     IOCAF              ;Get ready to detect next bit
    bra      Timeout_wait       ;Keep waiting
   
   
    END
« Last Edit: November 04, 2023, 07:22:16 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: jpanhalt

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?
« Reply #12 on: November 04, 2023, 09:52:09 pm »
@ David,

This project actually dates back to one of my first MCU projects in 2008 when I just used the sign bit to control threading (i.e., stop the carriage) on a small lathe.  That was very easy to do.  My eventual goal will look only at d5(sign) to d11, but I figured for development to read the full transmission.  Is d12 (decimal point) important?  Not for this scale using inches.  Resolution is limited to 4 places.   In fact, d6 is not important as the scale is less than 10 inches long, nor is d13 for me.

Right now, I have a lot on my mind with a personal matter.  Today was for this project.  I started at 3:30AM, and the afternoon was dedicated to Ohio State football (our state university team).  That team drives me crazy.  It starts cold, then gets going in the second half unless it is playing a pushover.  It won again today and is undefeated for the season, but its toughest opponent is yet to come. 

Tomorrow and most of Monday will be devoted to the personal matter.  I will get back to this project in earnest late Monday. 

I really appreciate your advice, as you freely offer code suggestions.  I will try that code.  I am not sure SPI will be useful, but will also give it a try.  I have used SPI before and with several projects, but that may not work here.  It is an intriguing idea, though, unique (to me) and is definitely worth a try.

Regards, John
 

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?[SOLVED]
« Reply #13 on: November 09, 2023, 05:40:23 pm »
The personal matter wasted more than a week.  Today, I had a clear mind and was able to do some thought.  Circuit has been simplified and the buffers deleted, despite Mitutoyo's suggestions.  That gives a non-inverted signal with inverted clock (i.e., capture data at clock low).  In the attached images, the REQ is measured  right at the connector , not MCU as before, and is true, i.e., active low.

I simplified the code and just poll  Ser_in  to start capturing data, then poll Clk_in for actual data.  Only 9 registers are used and the first 4 "bytes" are ignored, except as a signal to release the REQ line and let it go high (magenta trace).

So, what was the problem?  My clue was that the negative sign was not being captured, while data were doubled.  It was not that my bit_ctr or byte_ctr were wrong.  I was capturing the very first data before being sure the clock was low.  I marked with red that point.  That shifted the rest of the data.  The simple, obvious errors are usually the hardest to catch.  There are still some small glitches that should be easy to fix.

Corrected code:
Code: [Select]
     movlw     4              ;                                                 |B0
     movwf     bit_ctr        ;                                                 |B0
     movlw     low(d5)        ;initialize FSR0 for new data                     |B0
     movwf     FSR0L          ;                                                 |B0
     movlb     2              ;                                                 |B2
     bsf       LATA,Req       ;request data (short !REQ to ground)              |B2
     movlb     0              ;11/06/23                                         |B0
     btfsc     PORTC,0        ;Ser_in                                           |B0
     bra       $-1            ;check for falling edge on !Ser_in                |B0
     movlb     2              ;clock running, can release !REQ                  |B2
     bcf       LATA,Req       ;         "                                       |B2
     movlb     0              ;                                                 |B0
;start 11/9/23
     btfsc     PORTA,Clk_in   ;be sure clock is low
     bra       $-1            ;
;end 11/9/23
     call      GetData        ;                                                 |B0 
     nop
     call      ClrData        ;                   
     bra       Main           ;returns in B0                                    |B0

Attachments:
1) DS1Z...  Full data  (omitted are registers 1..4)
2) Expanded and highlighted error
3) Watch window for -0.1450
« Last Edit: November 09, 2023, 05:48:06 pm by jpanhalt »
 

Online jpanhaltTopic starter

  • Super Contributor
  • ***
  • Posts: 4245
  • Country: us
Re: Stymied: Why are my data sometimes doubled?[SOLVED]
« Reply #14 on: November 12, 2023, 10:51:49 am »
In case anyone is curious, here is working code as of this morning in release form.  The display is an older SparkFun 4x20.  It is flaky.   Delays are added to make it work.  With a better/faster display, they should not all be necessary.

The code includes a "clear data" routine.  As rotations are used to add each new 4-bit byte, and the older data is masked before printing with an "andwf INDF0,f" clearing old data is not required.  It might be useful to retain if one wanted to do something like calculate a feed rate.

This code and design (without the buffers) should work with any enhanced mid-range PIC, including the 12F1xxx.  With slight modification and software Put232, it should even work with a baseline 12F509.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf