PIC32MX+OV7670カメラ　カラートラッキング高速化 ステッピングモータ駆動をI2Cクライアント化

# I2C Client２台で、ステッピングモータを駆動して、トラッキング

<iframe width="560" height="315" src="https://www.youtube.com/embed/56e-Wwkomd0?si=-0F3PmffLRrypPdj" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

:::note
# 今回の概要
前回、ステッピングモータで水平、垂直方向のカラートラッキングを行いました。

このとき、PIC32MXで直接ステッピングモータ２台を制御していました。

**<font color="DeepPink">それを、２つのPIC16F1827をI2C Client(slave)として、ステッピングモータの励磁信号の出力を分担させました。</font>**

移動速度も速くなり、かなり滑らかにトラッキングできるようになり、手の動きに同期して、トラッキングできるようになりました。

![IMG_5127.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/5080f504-9e0c-59ab-0829-36e212d78184.jpeg)

:::

# I2Cクライアントを用いたステッピングモーター駆動。

![トラッキング概略図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/337d270d-cb1c-13d8-4543-95e509de6a09.jpeg)

# RAM上でのグラフィック描画
![RAM解説.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/b09d8422-17c9-23ef-f981-8fc396e80758.jpeg)


# 垂直方向のコード抜粋
```C:PIC16F1827 I2C Cilentサイド I2C処理関連
#include "Peripheral.h"
#include "I2C_MSSP1_Slave.h"

_i2cStruct i2cInfo;

void I2C1_Reg_Init_Slave(void)
{
    uint8_t val;
    SSP1STAT=0xC0;
    SSP1CON1=0x36;          //slave mode , 7bit address
    //SSP1CON1=0x3E;        //slave mode , 7bit address with interrupts
    SSP1CON2bits.SEN=1;     //0:Clock stretching is disable
    SSP1CON3bits.PCIE=0;
    SSP1CON3bits.SCIE=0;
    SSP1CON3bits.AHEN=0;
    SSP1CON3bits.DHEN=0;
    SSP1ADD=0x36;
    val=SSP1BUF;
    PIE1bits.SSP1IE=1;
   
}

void I2C1_Slave_Interrupt(void)
{
    uint8_t I2c1stat,i,buf;
    //---------MSSP1 ステータス読み出し---------
        PIR1bits.SSP1IF=0;
        I2c1stat=SSP1STAT & 0b00111101;
        
        /*1.--------I2c Writeモード　
                 スタートコンディション検出＆スレーブアドレス読み出し--------- */
        if(I2c1stat==0b00001001)
        {
            i2cInfo.index=0;
            for(i=0; i<=3; i++) i2cInfo.rxData[i]=0;
            i2cInfo.rxData[i2cInfo.index++]=SSP1BUF;    
            if(SSP1CON2bits.SEN==1)
                    SSP1CON1bits.CKP=1;
        }
        /*2.--------I2c Writeモード　受信データバイト読み出し---------*/
        if(I2c1stat==0b00101001)
        {
            i2cInfo.rxData[i2cInfo.index++]=SSP1BUF;
            /*if(i2cInfo.index==3)
            {//ストップビット検出ができない場合、ここで受信完了とする。
               i2cInfo.flag=true;//mainループで処理。
            }*/
            if(SSP1CON2bits.SEN==1)
                SSP1CON1bits.CKP=1;
        }
        /*3.--------I2c Readモード スタートコンディション検出&
                            データバイトバッファ出力 送信（アドレス部）--------- */
        if(I2c1stat==0b00001101)
        {
           
        }
        /*4.--------I2c Readモード　データバイトバッファ出力 送信（データ部）---------*/
        if(I2c1stat==0b00101100)
        {
           
        }
        /*5-1.--------I2c Writeモードストップビット検知---------*/
        if(I2c1stat==0b00110000)
        {
            if(i2cInfo.index==3)
            {
               i2cInfo.flag=true;//mainループで処理。
            }
            if(SSP1CON2bits.SEN==1)
            {
                SSP1CON1bits.CKP=1;
            }
        }
        /*5-2.---------I2c Readモードストップビット検知---------*/
        if(I2c1stat==0b00110100)
        {
             if(SSP1CON2bits.SEN==1)
                SSP1CON1bits.CKP=1;               
        }
}

```
```C:PIC16F1827 I2C Cilentサイド main.c

// PIC16F1827 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
//#pragma config FOSC = HS      // Oscillator Selection (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP =ON      // Low-Voltage Programming Enable (Low-voltage programming enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <stdlib.h>
#include <stdio.h>
#include "Interrupt.h"
#include "Peripheral.h"
#include "I2C_MSSP1_Slave.h"
#include "stepping.h"

#define _XTAL_FREQ  16000000

void Oscillator_Init(void);
void Port_Init(void);
void delay_ms(uint16_t time);






void main(void)
{    
    uint8_t cnt=0;
    uint8_t i,j,temp;
    uint8_t rxData;
    uint8_t  direction[2];
    
    //Basic Hard Initialize
    Oscillator_Init();
    Port_Init(); 
    //Peripheral 
    //Timer0_INIT();
    Timer2_INIT();
    //USART_INIT();
    //ADC_INIT();
    I2C1_Reg_Init_Slave();
    
    //famiconInit();
    //割り込み許可
    Interrupt_START();
    
    while(1)
    {
        //USART interrupt processing
        /*if(usart.rxCompleted)
        {
            usart.rxCompleted=false;
            printf("%s\n",usart.rxBuf);
            usart.length=0;
            PIE1bits.RCIE=1;
        }*/
        
        if(i2cInfo.flag)
        {
            i2cInfo.flag=false;
           
            rxData = i2cInfo.rxData[1];
           
            //printf("rcvData: %X %X\n",rcvdata[1],rcvdata[2]);
            //printf("RES:%02X\n",buttonState);
            if((rxData&0x04)==0x04)//Up
            {               
                st1UpMoving(1);
            }

            if((rxData&0x08)==0x08)//Down
            {               
                
                st1DownMoving(1);
            }
            
            if((rxData&0x10)==0x10)
            {
                LATAbits.LATA0=0;
                LATAbits.LATA1=0;
                LATAbits.LATA2=0;
                LATAbits.LATA3=0;
            }
            
        }
    }
    return;
}

void Oscillator_Init(void)
{
    OSCCONbits.SPLLEN=0;
    OSCCONbits.IRCF=0b1111;//16Mhz
    OSCCONbits.SCS=0b10;//InternalOscillator
}

void Port_Init(void)
{
    TRISA=0x00;
    ANSELA=0x00;
    TRISB=0x00;     //RX:RB2
    ANSELB=0x00;
    PORTA=0x00;
    PORTB=0x00;  
    //Altanative Pin Selective
    /*APFCON0bits.RXDTSEL=1;  //RX:RB2
    APFCON1bits.TXCKSEL=1;  //TX:RB5*/
    //I2Cinitialize
    TRISBbits.TRISB1=1;     //RB1
    TRISBbits.TRISB4=1;     //RB4
}


```

```C:ステッピングモータの励磁

#include "stepping.h"
#include "Peripheral.h"
unsigned int halfStep0[9]={0x0000,0x0001,0x0003,0x0002,0x0006,0x0004,0x000C,0x0008,0x0009};
unsigned int halfStep1[9]={0x0000,0x0010,0x0030,0x0020,0x0060,0x0040,0x00C0,0x0080,0x0090};




void st1UpMoving(uint8_t leftCount)
{
    uint8_t i;
    unsigned int j;
    for(i=0; i<leftCount; i++)
        for(j=1; j<=8; j++)
        {   
            LATA&=0xF0;
            LATA|=(uint8_t)halfStep0[j];
            __delay_us(stDelayUS);
            __delay_ms(20);
        }  
}

void st1DownMoving(uint8_t rightCount)
{
    uint8_t i;
    unsigned int j;
    for(i=0; i<rightCount; i++)
        for(j=8; j>=1; j--)
        {    
            LATA&=0xF0;
            LATA|=(uint8_t)halfStep0[j];
            __delay_us(stDelayUS);
            __delay_ms(20);
        }
}




```