Hi all.
I am working on a project using the BBB PRU and eQEP module. At given positions I am using a pulse to trigger the shutter on a camera that is pointed at the motor that is driving the encoder. For testing purposes I am attempting to get a pulse on every rotation so I can easily compare the image from one rotation to the next to confirm that I am properly trigging every rotation. ‘ This is my first time using the BBB, and it has been quite the learning experience. I have been using the AM335x technical reference manual <http://www.ti.com/lit/ds/symlink/am3358.pdf> (starts on page 1650) as a guide for doing this. The problem: Using an oscilloscope with the green probe attached to position compare sync output index pin (P8_31) and the red probe attached to the index input from the encoder on each rotation of the motor I am seeing the time between the pulses varying (see attached image Problem.gif, a picture is worth a thousand words). It is important to note that the system technically works, however because the difference in timing I am unable to capture the images that I need. The goal is to be able to consistently get the expected image. Things I have tried: Switching the sync output pulse between the strobe and index pins. No change in behavior. Adjusting the value put into the position-compare register. I tried both 4,001 and 3,999. In each case I still see variance between the position-compare sync output and the index pulse. Hooking the camera shutter up directly to the index pulse from the encoder and the resulting images show little to no change from one rotation to the next. The camera itself is hooked to a PC that is receiving the image. This confirms that my method for capturing images seems adequate. Questions: I am working on the assumption that the position-compare register on the eQEP module, when set to 4k for my encoder, should exactly match the index pulse coming from the encoder. Is this assumption correct? Are there any additional debugging steps I could take to determine why this is happening? Technical details: Linux beaglebone 3.8.13-bone84 #1 SMP Sun Feb 12 02:54:13 UTC 2017 armv7l GNU/Linux -- For more options, visit http://beagleboard.org/discuss --- You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/59108899-73df-48d3-98b8-00f0e93b1f21%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
.origin 0 .entrypoint START #include "PRU_encoder.hp" #define EQEP1 0x48302180 #define QPOSCNT 0x0 #define QPOSCMP 0xC #define QDECCTL 0x28 #define QEPCTL 0x2A #define QPOSCTL 0x2E #define QEINT 0x30 #define QFLG 0x32 #define QCLR 0x34 START: // Enable OCP master port LBCO r0, CONST_PRUCFG, 4, 4 CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port SBCO r0, CONST_PRUCFG, 4, 4 // Configure the block index register for PRU0 by setting c24_blk_index[7:0] and // c25_blk_index[7:0] field to 0x00 and 0x00, respectively. This will make C24 point // to 0x00000000 (PRU0 DRAM) and C25 point to 0x00002000 (PRU1 DRAM). MOV r0, 0x00000000 MOV r1, CTBIR_0 SBBO r0, r1, 0x00, 4 //The number of values to watch for LBCO r1, CONST_PRUDRAM, 4, 4 //LBCO r2, CONST_PRUDRAM, 8, 4 //The starting offset of the values MOV r2, 0x8 //Load the base address of the EQEP unit MOV r4, EQEP1 //Enable sync-output LBBO r5, r4, QDECCTL, 2 SET r5, r5, 13 //Sync output enable, 0=disabled, 1=enabled CLR r5, r5, 12 //Sync output pin 0=index, 1=strobe SET r5, r5, 10 //Swap quadrature-clock inputs SBBO r5, r4, QDECCTL, 2 //Enabled position compare interrupt LBBO r5, r4, QEINT, 2 CLR r5, r5, 11 //Disable timeout interrupt SET r5, r5, 8 //Enable position-compare match interrupt SET r5, r5, 7 //Enable position-compare ready interupt SBBO r5, r4, QEINT, 2 //Setup the eQEP Position-Compare Control LBBO r5, r4, QPOSCTL, 2 CLR r5, r5, 15 //Shadow disabled CLR r5, r5, 14 //Load on QPOSCNT = 0 SET r5, r5, 12 //Enabled Position-compare //Pins 0-11 control the width of the position-compare output pulse //0 = 1 x 4 x SYSCLKOUT //1 = 2 x 4 x SYSCLKOUT //2-FFF = 3 x 4 x SYSCLKOUT SET r5, r5, 0 SET r5, r5, 1 SET r5, r5, 2 SET r5, r5, 3 SET r5, r5, 4 SET r5, r5, 5 SET r5, r5, 6 SET r5, r5, 7 SET r5, r5, 8 SET r5, r5, 9 SET r5, r5, 10 SET r5, r5, 11 SET r5, r5, 12 SBBO r5, r4, QPOSCTL, 2 //Set the position counter to reset when the maximum position is reached LBBO r5, r4, QEPCTL, 2 SET r5, r5, 12 //Enabled position-compare unit SBBO r5, r4, QEPCTL, 2 //Causes the position to reset to 0 WAIT_FOR_POSITION: //Get next value and set it as the value to compare with LBCO r5, CONST_PRUDRAM, r2, 4 SBBO r5, r4, QPOSCMP, 4 //Clear interupts MOV r5, 0x0FFF //Clear all SBBO r5, r4, QCLR, 2 LOAD_LOOP: LBBO r5, r4, QFLG, 2 QBBC LOAD_LOOP, r5.t8 //Interrupt flg set, get next value //Add 4k to the position to watch for LBCO r9, CONST_PRUDRAM, r2, 4 MOV r8, 0xFA0 //0xFA0 == 4000 ADD r9, r9, r8 SBCO r9, CONST_PRUDRAM, r2, 4 //Stop if we have found all of the values QBEQ STOP, r1, 0 //Return to position compare loop JMP WAIT_FOR_POSITION STOP: // Send notification to Host for program completion MOV R31.b0, PRU0_ARM_INTERRUPT+16 HALT
/***************************************************************************** * Include Files * *****************************************************************************/ #include <stdio.h> // Driver header file #include <prussdrv.h> #include <pruss_intc_mapping.h> /***************************************************************************** * Explicit External Declarations * *****************************************************************************/ /***************************************************************************** * Local Macro Declarations * *****************************************************************************/ #define PRU_NUM 0 #define ADDEND1 0x0010F012u #define ADDEND2 0x0000567Au #define AM33XX /***************************************************************************** * Local Typedef Declarations * *****************************************************************************/ /***************************************************************************** * Local Function Declarations * *****************************************************************************/ static int LOCAL_exampleInit ( unsigned short pruNum ); static unsigned short LOCAL_examplePassed ( unsigned short pruNum ); /***************************************************************************** * Local Variable Definitions * *****************************************************************************/ /***************************************************************************** * Intertupt Service Routines * *****************************************************************************/ /***************************************************************************** * Global Variable Definitions * *****************************************************************************/ static void *pruDataMem; static unsigned int *pruDataMem_int; /***************************************************************************** * Global Function Definitions * *****************************************************************************/ int main (void) { unsigned int ret; tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; printf("\nINFO: Starting %s example.\r\n", "PRU_encoder"); /* Initialize the PRU */ prussdrv_init (); /* Open PRU Interrupt */ ret = prussdrv_open(PRU_EVTOUT_0); if (ret) { printf("prussdrv_open open failed\n"); return (ret); } /* Get the interrupt initialized */ prussdrv_pruintc_init(&pruss_intc_initdata); /* Initialize example */ printf("INFO: Initializing example.\r\n"); LOCAL_exampleInit(PRU_NUM); /* Execute example on PRU */ printf("INFO: Executing example.\r\n"); prussdrv_exec_program (PRU_NUM, "./PRU_encoder.bin"); /* Wait until PRU0 has finished execution */ printf("INFO: Waiting for HALT command.\r\n"); prussdrv_pru_wait_event (PRU_EVTOUT_0); printf("INFO: PRU completed transfer.\r\n"); prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); /* Check if example passed */ if ( LOCAL_examplePassed(PRU_NUM) ) { printf("INFO: Example executed succesfully.\r\n"); } else { printf("INFO: Example failed.\r\n"); } /* Disable PRU and close memory mapping*/ prussdrv_pru_disable (PRU_NUM); prussdrv_exit (); return(0); } /***************************************************************************** * Local Function Definitions * *****************************************************************************/ static int LOCAL_exampleInit ( unsigned short pruNum ) { //Initialize pointer to PRU data memory if (pruNum == 0) { prussdrv_map_prumem (PRUSS0_PRU0_DATARAM, &pruDataMem); } else if (pruNum == 1) { prussdrv_map_prumem (PRUSS0_PRU1_DATARAM, &pruDataMem); } pruDataMem_int = (unsigned int*) pruDataMem; return(0); } static unsigned short LOCAL_examplePassed ( unsigned short pruNum ) { return 1; }
PRU_encoder.hp
Description: Binary data