Jump to content

lukelouyu

Members
  • Posts

    24
  • Joined

  • Last visited

Posts posted by lukelouyu

  1. Hi, 

    I have been trying to use the zybo board timer interrupt functions to control my water pump while running other program, kind of like multitasking. 

    The program goes like this, when the my other programs are running in the while(true) loop (running forever), the water pump will turn on for 12 hours and turn off for 12 hours

    Before jumping into actual program, I made some simple testing. While the Pmod HYGRO is getting value, the led 4bits will have a loop of turning on for 100s and turning off 100s (like led toggling) 

    Here is what I have tried with built-in led:

    #include <stdio.h>
    #include "platform.h"
    #include "xil_printf.h"
    
    #include "xparameters.h";
    #include "xgpio.h";
    #include "xtmrctr.h";
    #include "xscugic.h";
    #include "xil_exception.h";
    
    #include "PmodHYGRO.h"
    #include "sleep.h"
    #include "xil_cache.h"
    
    
    #ifdef __MICROBLAZE__
    #define TIMER_FREQ_HZ XPAR_CPU_M_AXI_DP_FREQ_HZ
    #else
    #define TIMER_FREQ_HZ 100000000
    #endif
    
    PmodHYGRO myDevice;
    
    void DemoInitialize();
    void DemoRun();
    void DemoCleanup();
    void EnableCaches();
    void DisableCaches();
    
    
    // Parameter definitions
    #define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
    #define TMR_DEVICE_ID XPAR_TMRCTR_0_DEVICE_ID
    #define LEDS_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID
    #define INTC_TMR_INTERRUPT_ID XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR
    
    #define TMR_LOAD 0xF8000000
    
    
    XGpio LEDInst;
    XScuGic INTCInst;
    XTmrCtr TMRInst;
    
    static int led_data;
    static int tmr_count;
    
    //void print (char *str);
    
    static void TMR_Intr_Handler(void *baseaddr_p);
    static int IntcInitFunction (u16 DeviceId, XTmrCtr *TmrInstancePtr);
    
    void TMR_Intr_Handler(void *data){
    	if (XTmrCtr_IsExpired(&TMRInst,0)){
    		// Once timer has expired 3 times, stop, increase counter
    		//reset timer and start running again
    
    	if(tmr_count==3){
    		XTmrCtr_Stop(&TMRInst,0);
    				tmr_count=0;
    		//led_data++;
    				led_data=~led_data;
    		XGpio_DiscreteWrite(&LEDInst,1,led_data);
    
    		XTmrCtr_Reset(&TMRInst,0);
    		XTmrCtr_Start(&TMRInst,0);
    
    	}else
    		tmr_count++;
    
    	}
    }
    
    // Initial Setup Functions
    
    int InterruptSystemSetup(XScuGic *XScuGicInstancePtr){
    	// Enable Interrupt
    
    	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
    			XScuGicInstancePtr);
    	Xil_ExceptionEnable();
    
    	return XST_SUCCESS;
    
    }
    
    
    int IntcInitFunction (u16 DeviceId, XTmrCtr *TmrInstancePtr){
    XScuGic_Config *IntcConfig;
    int status;
    
    //Interrupt controller initialisation
    IntcConfig=XScuGic_LookupConfig(DeviceId);
    status= XScuGic_CfgInitialize(&INTCInst, IntcConfig,
    		IntcConfig->CpuBaseAddress);
    if (status!= XST_SUCCESS)
    	return XST_FAILURE;
    
    //Call to interrupt setup
    status= InterruptSystemSetup(&INTCInst);
    if (status != XST_SUCCESS)
    	return XST_FAILURE;
    
    // Connect timer interrupt to handler
    status= XScuGic_Connect(&INTCInst, INTC_TMR_INTERRUPT_ID,
    		(Xil_ExceptionHandler) TMR_Intr_Handler, (void*) TmrInstancePtr);
    if (status != XST_SUCCESS)
    	return XST_FAILURE;
    
    // Enable timer interrupts in the controller
    XScuGic_Enable(&INTCInst, INTC_TMR_INTERRUPT_ID);
    
    return XST_SUCCESS;
    
    }
    
    
    
    int main()
    {
        init_platform();
    
        led_data=0;
        int status;
        // INITIALISE THE PERIPHERALS & SET DIRECTIONS OF GPIO
    
        // Initialise LEDs
        status=XGpio_Initialize(&LEDInst, LEDS_DEVICE_ID);
        ;
        if (status != XST_SUCCESS)
        	return XST_FAILURE;
    
        // Set LEDs direction to outputs
        XGpio_SetDataDirection(&LEDInst, 1,0x00);
    
        //Initilise interrupt controller
        status=IntcInitFunction(INTC_DEVICE_ID, &TMRInst);
        if (status != XST_SUCCESS)
        	return XST_FAILURE;
    
        // Set the TIMER
        status= XTmrCtr_Initialize(&TMRInst, TMR_DEVICE_ID);
        	    if (status != XST_SUCCESS)
        	    	return XST_FAILURE;
        XTmrCtr_SetHandler(&TMRInst, (XTmrCtr_Handler) TMR_Intr_Handler, &TMRInst);
        XTmrCtr_SetResetValue(&TMRInst,0,TMR_LOAD);
        XTmrCtr_SetOptions(&TMRInst,0,
        		XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION);
    
       XTmrCtr_Start(&TMRInst,0);
    
    
        while(1)
        	 DemoInitialize();
        	   DemoRun();
        	   DemoCleanup();
    
    
    
    
        return 0;
    }
    
    void DemoInitialize() {
       EnableCaches();
       xil_printf("Init Started\n\r");
       HYGRO_begin(
          &myDevice,
          XPAR_PMODHYGRO_0_AXI_LITE_IIC_BASEADDR,
          0x40, // Chip address of PmodHYGRO IIC
          XPAR_PMODHYGRO_0_AXI_LITE_TMR_BASEADDR,
          XPAR_PMODHYGRO_0_DEVICE_ID,
          TIMER_FREQ_HZ // Clock frequency of AXI bus, used to convert timer data
       );
       xil_printf("Init Done\n\r");
    }
    
    void DemoCleanup() {
       DisableCaches();
    }
    
    void DemoRun() {
       float temp_degc, hum_perrh, temp_degf;
       while (1) {
          temp_degc = HYGRO_getTemperature(&myDevice);
          temp_degf = HYGRO_tempC2F(temp_degc);
          hum_perrh = HYGRO_getHumidity(&myDevice);
          xil_printf(
             "Temperature: %d.%02d deg F  Humidity: %d.%02d RH\n\r",
             (int) temp_degf,
             ((int) (temp_degf * 100)) % 100,
             (int) hum_perrh,
             ((int) (hum_perrh * 100)) % 100
          );
          // %f does not work with xil_printf
          // instead, converting float to a pair of ints to display %.2f.
    
          // 1 sample per second maximum, as per 9.2.1 in HDC1080 reference manual
          sleep(1);
       }
    }
    
    void EnableCaches() {
    #ifdef __MICROBLAZE__
    #ifdef XPAR_MICROBLAZE_USE_ICACHE
       Xil_ICacheEnable();
    #endif
    #ifdef XPAR_MICROBLAZE_USE_DCACHE
       Xil_DCacheEnable();
    #endif
    #endif
    }
    
    void DisableCaches() {
    #ifdef __MICROBLAZE__
    #ifdef XPAR_MICROBLAZE_USE_ICACHE
       Xil_ICacheDisable();
    #endif
    #ifdef XPAR_MICROBLAZE_USE_DCACHE
       Xil_DCacheDisable();
    #endif
    #endif
    }

    Here is Vivado block diagram: 

    image.thumb.png.fd670b30361b484478c7852b9f61942a.png

     

    Here are some issues faced:

    1) when i change value in "if(tmr_count==3)" to a large value, the time of toggling is still within 3s. (if there is no HYGRO code) 

    2) the led does not function, but the HYGRO functions when there is code for HYGRO

    If anyone can also help me or give me suggestion on water pump timer control, I will be so much appreciate it. I will upload my Vivado block design and Vitis code below for your reference. 

    Thanks

    Luke Louyu. 

    BlockDesignNew.PNG

    New Code V1.0.txt

  2. Hi, everyone here.

    Now, I have tried with my Pmod AD1. I used the demo code provided by the Digilent, but the value shown in the Vitis Serial Terminal is different from the value I have seen in the multimeter. 

    For example, when I insert my sensor A into the channel A0, the value shown in 2.56. The value shown in the multimeter is 2.9V.

    When I insert my sensor B into the channel A1, the value shown in  the Vitis Serial Terminal is 1.08. The value shown in the multimeter is about 2.1V.

    When the sensor induced voltage exceeds 1.8V, the AD1 value returns back to 0. 

    I think this diagram might tell me the reason. But I am not sure since I am new to FPGA & electronic and I don't quite understand the datasheet. (Link: https://www.analog.com/media/cn/technical-documentation/evaluation-documentation/AD7476A_7477A_7478A.pdf?_ga=2.196220652.1995249494.1621070558-1887244704.1616928603)

    image.png.8b6c63fb0d1ba8ccc7c59177d209688b.png

    Through comparing with the AD1 reading voltage and the multimeter voltage, i found there is an linear relationship between them. I made an excel file to show you guys the relationship. 

    image.png.141e8d178cb43768099c08f8dc736f95.png

    image.png.d35cd4f23c5826ea50309e4c5b23737d.png

     

    I suspected i need to add an additional voltage source but not sure as well. When I connects the Vcc to the D0 or D1, the serial terminal said 3.3V. I did not change anything in the demo code, is there anyway to allow the AD1 reading to be the same as the reading in the multimeter. 

     

    Thanks

    Luke

×
×
  • Create New...