stm32F407vg อยากได้ตัวอย่างวิธีการอ่าน Hall sensor และ encode + input capture สำเร็จแล้วครับ

Started by REDLINETECH, September 27, 2013, 12:17:04 PM

Previous topic - Next topic

REDLINETECH

ขอไหว้วอนสิ่งศักดิ์สิทธิ์ ดลให้ผู้รู้มาอธิบายเป็นวิทยาทานด้วยเถิดครับ แฮ่ เจ้า stm 32f407discu ของทาง st นี่แหละ พยายามอ่าน Hall sensor จนจะเป้นลม ยังหาทางไม่เจอ สัญญาณ oc1 , oc1n , oc2 , oc2n , oc3 , oc3n ไม่รู้เขาจะออกทางขาไหนเซ็ทคอนฟิกยังไง แต่ตัวอ่านเอนโค๊ดเดอร์ อ่านได้แล้ว แต่จะทำการอ่านด้วยแคปเจอร์ด้วยยังไม่ได้ ตอนนี้ใช้วิธิ ต่อขาไป TIM ตัวอื่นแคบแทน ยังไงฝากผู้รู้ด้วยนะครับ จะขอบพระคุณมาก ตามโค๊ดผมที่อ่านเอนโคํดเดอร์ ตามนี้ครับ อาจจะเทอะทะนะเพราะมือใหม่จริงๆ ช่วยชี้แนะด้วยครับ

void encoder(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//EXTI_InitTypeDef EXTI_InitStructure;
  //*************************encoder********************************************
  //Enable or disable the AHB1 peripheral clock
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
        //Configure GPIO pin
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz ;
          GPIO_InitStructure.GPIO_OType = GPIO_OType_PP ;
          GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
                //Configure GPIO pin
                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ;
                  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz ;
                  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP ;
                  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
                GPIO_Init(GPIOB, &GPIO_InitStructure);
        //Configure GPIO pin alternate function
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2);
        //Configure GPIO pin alternate function
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_TIM2);
        // TIM2 clock enable
               RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//
        TIM_SetAutoreload (TIM2, 0xffffffff);

        //**********************************************************************
       /* Enable the TIM1 global Interrupt */
       NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
       NVIC_Init(&NVIC_InitStructure);
     //*******************************************************************

        TIM_Cmd (TIM2, ENABLE);
        TIM_SetCounter (TIM2, 0);
        // NVIC_EnableIRQ(TIM2_IRQn); // Interrupt Enable
         //  a = TIM_GetCounter  (TIM2);

  //***************************end encoder*****************************************
}



tha

ผมเคยลองใช้ encoder mode กับ stm32f103rbt6 กับ dc motor ตัวนี้
http://sangtawan.org/product_detail.asp?product_id=810&lng=th
ตัว drive เป็น L298N ซึ่งผมว่าไม่ค่อยเหมาะกับตัว motor เท่าไหร่ แต่ก็ทำงานได้
อันนี้เป็นตัวอย่างปรับ speed ด้วย adc
http://www.mediafire.com/download/k827m4mnehc7lio/ET-STM32F103_NOKIA5110_Encoder_DCmotor_PWM.rar
อันนี้เพิ่ม pid control เข้าไปด้วย นานแล้วชักจะลืม
http://www.mediafire.com/download/8cv5b6lggkg67r9/ET-STM32F103_NOKIA5110_Encoder_DCmotor_PID.rar
ระวังบาง pin ต้องทนไฟ 5v ด้วยนะครับถ้าไฟเข้า 5v

tha

อันนี้ผมลองทำ balancing robot ใช้ stm32f3discovery แต่ไม่สำเร็จคิดว่าปัญหามาจากตัว drive L298N ไม่สมูดพอ
http://www.mediafire.com/download/09ouyyvnzoqh222/Balancing_Robot_1.rar


deejun

ผมไม่ถัดใช้ LIB  แต่เดาๆว่าท่านเจ้าของกระทู้จะทำอะไรกับ มอเตอร์สามเฟส  ประเภคบัชแลท หรือ BLDC motor หรือเปล่า
ปรับสปีด   ลองหาอ่านพวก Timer ที่โพทไว้ดู คู่กับ PWM ที่โพท น่าจะพอแก้ขัด แก้กระใสได้แล
STM32F4 ผมก็คงหหยุดไว้แค่นี้ เหมาะแก่การเริ่มศึกษา   ไว้เยอะแล้ว  ที่เหลือให้ท่านที่ต้องการไปศึกษาเอาเอง
ทำมากกว่านี้เดี๋ยวจะมีคนก็อปปี้ไปทำหนังสือขาย  แล้วผมกลายเป็นตัวก๊อปปี้หนังสือแทน  :D

ทำขับธรรมดากับ อินเวิดไม่ยากครับ แต่ให้ดี ศึกษาแบบธรรมดาก่อนให้เป็น สร้างพลัลให้ได้ 50%ก่อน และเปลี่ยนความถี่ให้ได้
แล้วถึงจะสร้างตัวอินเวิดชันแนล มา และใส่ เดททาม(กันตายลงไป)  ถ้าท่านทำแบบ Register อาจจะพอคุยกันได้ง่าย
ครับผม

REDLINETECH

ใช่ครับ ผมกำลังศึกษาการขับมอเตอร์ BLDC ตัวใหญ่ๆอยู่ครับ แบบปัญญาน้อย ความทะเยอทะยานสูง ประมาณนี้ :D  ขอบคุณมากสำหรับแชร์วิชาการครับ ถ้าไม่มีกระทู้ เวบบอร์ดดีๆแบบนี้ ผมคงไม่มีทางคิดเรื่องนี้หรอก ท่านๆคือแรงผลักดัน แชร์วิชาการกันครับ ขอบคุณมากๆ

deejun

ผมก็ไม่เคยทำเช่นกันครับ เคยสนใจอยู่เท่านั้น  แต่สัญญาณขับคล้ายๆที่เคยเอาไปขับ
หม้อแปลงความถี่สูง แบบมัลติเฟส  (สามเฟส)  น่าจะขับได้อยู่ลองดูครับ ปรับดู

1- เลือก Timer ตัวไหนก็ได้  T1,T2.......  เอามา 1 ตัวใช้ทำ Interrupt Timer สมมุตว่าใช้  T2  ก็ทำการ setค่าใช้งาน Timer2
2- เลือก GPIO ที่ใช้ขับอะไรก้ได้    สมมุติเลือก GPIOC  Bit 0, Bit1, Bit2, Bit3, Bit4, Bit5   ใช้เป็น Output
    เลือกมา  6 ขา  6 bit   เพราะว่าไดร์สวิต  6 ชุดนั้นเอง  และเพื่อให้ง่าย  เรียงลำดับกันไป
3- BLDC Motor ใช้ไดร์ 6 สเต็ป  ดังนั้นจะมีค่า 6 ค่าในการเปลี่ยนแปลงให้ง่าย สร้าง look up table ค่าขึ้นมา  6 ค่า
    สมมุติ   ตัวแปร     int Step[] = {26,42,41,37,21,22};  ค่านี้มาจากตารางไดร์ หาอ่านได้จากเอกสารทั่วไปหรือทางค่าย microchip ก็ได้มีเยอะมาก
 
    ตั้ง Timer ให้เกิดการอิเตอร์รัป  เพื่อใช้ในการเปลี่ยนสเต็ปการทำงานและความเร็วรอบก็อยู่ที่จุดนี้ด้วยแต่ระวังว่าถ้าไปขับ
    ความถี่ต่ำๆ การแช่เฟสนานเกินไปอาจทำให้ลวดไหม้ได้  ถ้าหมุนรอบต่ำๆต้องระวังจะมีเทคนิคในการมอดความถี่เข้าไปอีก
    ในที่นี้เป็นขับธรรมดาก่อน ถ้าขับช้าก็ลดแรงดันในการทดลองก่อนเพื่อศึกษาโปรแกรมและการขับ
    เช่นมอเตอร์  120V  ก็อาจจะขับแค่   50V  ก่อน   ใช้วาริแอตปรับแรงดันลดทอนก่อนเป็นต้นหรือหม้อแปลงก็แล้วแต่
    ป้องกันผิดพลาด

4 ในลูป Timer interrupt_Timer2                               //  ปรับความเร็วปรับที่ Timerนี้
                                  {
                                    GPIOC    =     0;                       // เคลียร์ค่าพอท
                                    delay_us(5);                            //  ทำ เดททาม ป้องกันสวิตชันกัน
                                    GPIOC    =     Step[Counter];   //  ดึงข้อมูลจากตาราง การหมุน
                                    Counter  =    Counter+1;         //  เปลี่ยนสเต็ปการหมุน
                                    if(Counter>5)                        //  ถ้าสเต็ปการทำงานเท่ากับ 6 ให้กลับไปวนที่ตำแหน่งแรกต่อ
                                    Counter  =    0
}
                               
   Sw0     =     สวิตบนซ้าย    GPIOC_Bit0
   Sw1     =     สวิตล่างซ้าย   GPIOC_Bit1
   Sw2     =     สวิตบนกลาง   GPIOC_Bit2
   Sw3     =     สวิตล่างกลาง  GPIOC_Bit3
   Sw4     =     สวิตบนขวา     GPIOC_Bit4
   Sw5     =     สวิตตัวล่างขวา GPIOC_Bit5             

อันนี้เหมาะความเร็วปานกลางที่ไม่ช้าไปพอลองได้
...
ถัดมาในการขับความถี่ต่ำๆแช่คอยนานๆอาจมีปัญหาได้ ให้ทำการมอดความถี่เข้าไปร่วมกับความถี่ต่ำเช่น  สมมุติว่า ขับที่ความถี่  2Hz
มอเตอร์หมุน1รอบใช้เวลา   T=1/f    ,T=1/2   =  0.5S  อาจทำให้มอเตอร์แช่กระแสนานจนร้อนได้   
ให้ทำการมอดความถี่   1-3Khz เข้าไป   วิธีง่ายสุด คือใช้ Timer อีกตัวมาช่วง
สร้าง Timer อีกตัว ,อินเตอร์รัฟ  ทุกๆ 2เท่าของความถี่ที่เลือก   เพราะว่า  1คาบเวลาเกิด 2 ครั้งนั้นเอง
เลือกความถี่ มอด    1Khz  ดังนั้นต้องสร้างความถี่ อินเตอร์รัฟจากทามเมอร์ที่  2Khz  นั่นเอง

เลือก T3 มาเป็นตัวอินเตอร์รับ และสร้างเคาร์เตอร์มา1ตัวใช้นับ 2 จังหวะ   1 รีเซท    2อับโหลดค่า
เคาท์เตอร์ให้ชื่อ  int Pulse  และเซ็ทค่าต่างๆให้ได้อินเตอร์รัฟที่ 2 Khz

ลูป Timer interrupt_Timer3            //   เปลี่ยนความถี่มอดเปลี่ยนจาก Timerนี้
                                        {
                                          GPIOC     =       0;                    //  เครียร์ค่าไดร์
                                          delay_us(5);                            //  สร้างเดททาม
                                          if(Pulse==0)                            //   เช็คค่าตัวนับ
                                          GPIOC    =        0;                   //   เครียร์ค่า
                                          else                                        //   ตรวจสอบ   
                                          GPIOC    =        Step[Counter];    // กลับไปค่าในเฟสตำแหน่งเดิม 
                                          Pulse       =       Pulse+1;             //  เปลี่ยนสเต็บการมอด
                                          if(Pulse>1)                                  //   ตรวจสอบตัวนับ
                                          Pules       =      0                         //    กลับเริ่มทำงานตัวนับ
                                         


}

REDLINETECH

ขอบคุณมากๆครับสำหรับแนวคิดท่านdeejun กำลังลองทดสอบอยู่ครับ ผมเห็นในดาต้าชีทของ stm32f4xx เขามีTIM สำหรับ hall sensorโดยเฉพาะ น่าสนใจมากๆท่านใดเคยใช้งานTIM ตัวนี้บ้างครับ

tha

อ่าน reference manual แล้วยังไม่ค่อยเข้าใจเหมือนกัน ฟังชั่นนี้ใช้ขับมอเตอร์สามเฟสเหรอครับ? น่าสนใจ ยังไม่เคยทำเคยทำแต่ขับ dc motor ที่มี encoder มีตัอย่างปรับค่า pid โดยทาง uart เพื่อให้ได้ค่าที่เหมาะสมโดยที่ไม่ต้องโปรแกรมใหม่ ทำเป็นการปรับ speed แบบ close loop
http://www.mediafire.com/download/bfq2a046k0ps11p/ET-STM32F103_NOKIA5110_Encoder_DCmotor_PID_USART_DMA.rar