物料名称 | 型号 | 功能 |
OPENMV模组 | OPENMV CAM H7 | 采集图像、面部朝向判断 |
STM32 | NUCLEO-L476RG | USB Host、主控板 |
STM32 | STM32F070 | USB Device |
import sensor
import time
import image
import pyb
from machine import LED
global calib
def callback_p0(line):
calib = 1
def main():
sensor.reset()
sensor.set_contrast(8)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
calib = 0
midpoint = 0
stat = 1
nowpoint = 0
led1 = LED("LED_BLUE")
led2 = LED("LED_RED")
led3 = LED("LED_GREEN")
p0_h = pyb.Pin("P0", pyb.Pin.IN)
p1_h = pyb.Pin("P1", pyb.Pin.OUT_PP)
p2_h = pyb.Pin("P2", pyb.Pin.OUT_PP)
p1_h.low()
p2_h.low()
p0_ext = pyb.ExtInt(p0_h, pyb.ExtInt.IRQ_FALLING,
pyb.Pin.PULL_UP, callback_p0)
face_cascade = image.HaarCascade("frontalface", stages=25)
while True:
img = sensor.snapshot()
objects = img.find_features(face_cascade, threshold=1, scale_factor=1.5)
for face in objects:
if(calib):
nowpoint = (face[0]+face[2])/2
calib = 0
led3.on()
pyb.delay(5000)
led3.off()
nowpoint = (face[0]+face[2])/2
if((nowpoint <= midpoint) and (stat == 1)):
led1.off()
led2.on()
stat = 2
p1_h.low()
p2_h.high()
elif(nowpoint>midpoint) and (stat == 2):
led2.off()
led1.on()
stat = 1
p2_h.low()
p1_h.high()
NUCLEO-L476RG开发板用于实现USB Host,操作键鼠一体USB接收器,将USB HID报文中的数据转发到SPI输出。根据OPENMV的GPIO的电平进行处理:若GPIO1的电平为高,则说明此时人脸是朝向左侧的,此时对应左侧电脑的SPI slave (STM32F070,实现左测电脑的USB输入设备)片选信号置为有效,HID报文数据被SPI slave接收后通过USB端点发送出去;若GPIO2的电平为高,则说明此时人脸是朝向右侧的,另一个SPI slave的片选信号有效,HID报文被转发到另一个USB设备发出。
如果键盘鼠标是独立的(要两个USB口),则需要增加一个USB host来处理,就需要再用一块STM32L476或类似的带USB-OTG设备的MCU,将其收到的HID报文发送给主控的STM32L476. 因为大赛物料成本的限制,手上又有无线键鼠套装,就只用了一个USB host.
int main(void)
{
gpio_config();
GPIOB->OSPEEDR = 2<<30|2<<28|2<<26;
FLASH->ACR = FLASH_ACR_ICEN|FLASH_ACR_DCEN|FLASH_ACR_PRFTEN
|2<<FLASH_ACR_LATENCY_Pos; // 2 wait states, 32~48MHz
clk_config(); // without this, default SYSCLK is 4MHz
uart_setup();
if((RCC->CFGR & RCC_CFGR_SWS_Msk)!=RCC_CFGR_SWS_PLL)
{
uart_wstr("Clock setting to PLL failed. ");
}
spi_setup();
usb_setup();
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM6EN;
__NOP();
TIM6->PSC = 479; // prescale to 100kHz
TIM6->EGR = TIM_EGR_UG; // generate update
TIM6->SR = 0; // clear interrupt flag
TIM6->DIER = TIM_DIER_UIE; // enable Interrupt
NVIC_EnableIRQ(TIM6_DAC_IRQn);
while(1)
{
__WFI();
}
}
int main(void)
{
int i;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN|RCC_APB2ENR_SPI1EN;
gpio_config();
FLASH->ACR=FLASH_ACR_PRFTBS|FLASH_ACR_PRFTBE|FLASH_ACR_LATENCY;
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
clock_setup();
config_spi_slave();
uart_setup();
uart_whex(SPI1->CR2);
uart_wstr(" F070 test\r\n");
NVIC_EnableIRQ(SPI1_IRQn);
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
USB->CNTR &= ~1; // remove PDWN
delay_ms(1);
USB->CNTR = 0; // no reset
USB->CNTR = USB_CNTR_CTRM|USB_CNTR_WKUPM|USB_CNTR_ERRM
|USB_CNTR_SUSPM|USB_CNTR_RESETM;
uart_wstr("Configured USB_CNTR\r\n");
NVIC_EnableIRQ(USB_IRQn);
USB->BCDR = USB_BCDR_DPPU; // pull-up resistor enable
while(1)
{
static char row=0;
__WFI();
if(ep0_state & 0x80) // request data processing
{
if(ep0_state==0x80) // SETUP phase
{
if(!setup_packet_service())
{
ep0_state=0;
uart_wstr("NOT_SUPPORTED [Type ");
uart_whexb(ep0_std_req->bmRequestType);
uart_wstr(" Request ");
uart_whexb(ep0_std_req->bRequest);
uart_wstr(" Val ");
uart_whexh(ep0_std_req->wValue);
uart_wstr(" Ind ");
uart_whexh(ep0_std_req->wIndex);
uart_wstr(" Len ");
uart_whexh(ep0_std_req->wLength);
uart_wstr("] ");
}
// ep0_state should be set to 1 or 2, if processed
}
else // OUT phase
{
ep0_state=4;
ep0_reenable_tx(0); //zero data, status stage
}
}
else
{
if(usb_address && ep0_state==0)
{
USB->DADDR = USB_DADDR_EF|usb_address;
usb_address=0;
}
}
}
}