Arduinoにカメラモジュール(OV7670 FiFo無)をつないでみた 　［その２　画像の表示］

## 概要
　[その１][その３][その４]で作成したカメラ(Arduino)から、送信されるデーターを画像として表示する。
## 内容
１．表示画面
　(1)表示例(QVGA)
![QVGA_Mono.jpg](https://qiita-image-store.s3.amazonaws.com/0/159764/aedc3bed-46df-f559-72d4-abd6e68259dd.jpeg)
　(2)操作方法
　　1)画像サイズ選択
　　　ラジオボタンで画像サイズ(VGA,QCGA,QQVGA)を選択する。
　　2)画像モード選択
　　　Colorを選択するとカラーになる。
　　3)通信モード選択
　　　SPDを選択すると、通信時間が短縮される。
　　4)キャプチャー選択
　　　capcureを押すと、画像を一枚表示。
　　　　※VSYNCに同期してから表示開始。
　　　repeatを押すと、連続して画像を表示。
　　　dispを押すと、バッファ内の画像を表示。
　　　　※通信エラー等で表示されない時に確認に使用する
　　5)通信ポート選択
　　　Arduinoが接続されているポート名を記入(初期はCOM1)
　　　　※回線がオープンできない場合は、赤く表示される
　　6)手動コマンド操作
　　　sendを押すとOV7670にコマンドを発行。
　　　　※コマンドはsend釦の前のボックスに、rrddの形(rr=レジスタ、dd=書込みデータ)で記入

２．ソフト

　(1)開発言語　
　　　visual basic (VS Express 2013 for Desktop)
　(2)作成方法
　　1) visual studioをインストール
　　2) visual basicの新規プロジェクトを立ち上げ
　　3) 初期作成されたファイル(Fom1.vb,Form1.Designer.vb)と下記(3)(4)を差し替え
　(3)「Form1.vb」(Ver1.2)　
　　　1)カラー化、スピードアップ対応
　　　2)VGA,QQVGA画像表示対応

```
Public Class Form1
    Dim picbfp, picdbp, pmmhd
    Dim img As New Bitmap(640, 480)
    Dim rcvbf As Byte()
    Dim picbf As Byte() = New Byte(800000) {}
    Dim picdb As Byte() = New Byte(800000) {}
    Dim cmode, smode, vmode, cspeed, picsp

    Private Sub com_open(comno As String, speed As Integer)
        If SerialPort1.IsOpen = True Then SerialPort1.Close()
        On Error Resume Next
        SerialPort1.PortName = comno
        SerialPort1.BaudRate = speed
        SerialPort1.StopBits = 1
        SerialPort1.Handshake = False
        SerialPort1.RtsEnable = False
        SerialPort1.Open()
        On Error GoTo 0
        If SerialPort1.IsOpen = False Then
            text2.ForeColor = Color.Red
        Else
            text2.ForeColor = Color.Black
        End If
    End Sub
    Private Sub espcheck()
        cspeed = 1000000
        com_open(text2.Text, cspeed)
    End Sub
    Private Sub modecheck()
        If CheckBox1.Checked = True Then
            cmode = 1
        Else
            cmode = 0
        End If
        If CheckBox2.Checked = True Then
            smode = 1
        Else
            smode = 0
        End If
        If RadioButton1.Checked = True Then
            vmode = 1 ' VGA
            PictureBox1.Width = 640 : Me.Width = 640 + 30
            PictureBox1.Height = 480 : Me.Height = 480 + 120
            smode = 0 ' No Select
        ElseIf RadioButton2.Checked = True Then
            vmode = 0 ' QVGA
            PictureBox1.Width = 320 : Me.Width = 320 + 30
            PictureBox1.Height = 240 : Me.Height = 240 + 120
        ElseIf RadioButton3.Checked = True Then
            vmode = 2 ' QQVGA
            PictureBox1.Width = 320 : Me.Width = 320 + 30
            PictureBox1.Height = 240 : Me.Height = 240 + 120
        End If
        If SerialPort1.IsOpen = True Then
            SerialPort1.WriteLine("c" + Chr(&H30 + vmode * 4 + smode * 2 + cmode))
        End If
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'pmmhd = "P5" + Chr(10) + "320 240" + Chr(10) + "255" + Chr(10)
        'Dim bytesData As Byte()
        'bytesData = System.Text.Encoding.UTF8.GetBytes(pmmhd)
        cmode = 0 : smode = 0 : vmode = 0
        modecheck() : espcheck()
        picsp = -1 : picbfp = 0
    End Sub

    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
        SerialPort1.Close()
    End Sub

    Delegate Sub DataDelegate(ByVal sdata As String)
    Private Sub PrintData(ByVal sdata As String)
        Text3.Text = sdata
    End Sub
    Delegate Sub DataDelegate2(ByVal sdata As String)
    Private Sub PrintData2(ByVal sdata As String)
        Dim px, py
        If vmode = 1 Then
            px = 640 : py = 480
        ElseIf vmode = 0 Then
            px = 320 : py = 240
        Else
            px = 160 : py = 120
        End If
        If cmode = 0 Then dispmono(px, py) Else dispcolor(px, py)
        PictureBox1.Image = img
        'picbfp = 0
    End Sub
    Private Sub dispcolor(px, py)
        Dim r, g, b
        Dim p, q, s, i, j, k
        For i = 0 To py - 1
            s = px \ 2 ' 80
            For j = 0 To px - 1
                If vmode = 2 And smode = 1 Then

                    k = j * 2
                    If (k Mod 4) = 0 Then
                        p = i * px * 2 + k \ 4
                    Else
                        p = i * px * 2 + s : s = s + 1
                    End If
                    k = j * 2 + 1
                    If (k Mod 4) = 0 Then
                        q = i * px * 2 + k \ 4
                    Else
                        q = i * px * 2 + s : s = s + 1
                    End If
                    Debug.Print(p.ToString + " " + q.ToString)
                ElseIf smode = 1 Then
                    p = i * px * 2 + j : q = p + px
                Else
                    p = (i * px + j) * 2 : q = p + 1 ' nomal
                End If
                r = picbf(p) And &HF8
                g = (picbf(p) And &H7) * 32 + (picbf(q) And &HE0) \ 8
                b = (picbf(q) And &H1F) * 8
                Dim c As Color = Color.FromArgb(r, g, b)
                img.SetPixel(j, i, c)
            Next
        Next
    End Sub
    Private Sub dispmono(px, py)
        Dim i, j, p, s
        For i = 0 To py - 1
            s = px \ 4 ' 40
            For j = 0 To px - 1
                If vmode = 2 And smode = 1 Then
                    If (j Mod 4) = 0 Then
                        p = i * px + j \ 4
                    Else
                        p = i * px + s : s = s + 1
                    End If
                ElseIf smode = 1 Then
                    p = i * px + j \ 2 + (j Mod 2) * px \ 2
                Else
                    p = i * px + j
                End If
                Dim r = picdb(p)
                Dim g = r
                Dim b = r
                Dim c As Color = Color.FromArgb(r, g, b)
                img.SetPixel(j, i, c)
            Next
        Next
    End Sub
    Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim sp, rl, rmax
        rcvbf = New Byte(SerialPort1.BytesToRead - 1) {}
        rl = rcvbf.GetLength(0)
        SerialPort1.Read(picbf, picbfp, rl) ' recv to picbf
        If picsp = -1 Then
            For sp = 0 To rl - 1
                If picbf(picbfp + sp) = &HFF Then
                    Buffer.BlockCopy(picbf, picbfp + sp + 1, picbf, 0, rl - 1) ' move to top
                    picsp = sp : rl = rl - sp - 1 : picbfp = 0
                    Exit For
                End If
            Next
        End If
        picbfp = picbfp + rl
        Dim adre As New DataDelegate(AddressOf PrintData)
        Me.BeginInvoke(adre, "[" + picbfp.ToString + "]")
        If vmode = 2 Then
            rmax = 19200 * (cmode + 1)
        Else
            rmax = 76800 * (vmode * 3 + 1) * (cmode + 1)
        End If
        If (picbfp >= rmax) Then
            Buffer.BlockCopy(picbf, 0, picdb, 0, picbfp)
            picsp = -1 : picbfp = 0
            Dim adre2 As New DataDelegate(AddressOf PrintData2)
            Me.BeginInvoke(adre2, "") 'Me.Invoke(adre, "")
        End If

    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs)
        SerialPort1.Close()
        End
    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        PrintData2("")
        picbfp = 0
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        SerialPort1.WriteLine(text1.Text)
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        SerialPort1.DiscardInBuffer()
        picbfp = 0
        Text3.Text = ""
        SerialPort1.WriteLine("c")
    End Sub

    Private Sub text2_TextChanged(sender As Object, e As EventArgs) Handles text2.TextChanged
        If (text2.Text.Length >= 4) Then com_open(text2.Text, cspeed)
    End Sub

    Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
        SerialPort1.WriteLine("r")
    End Sub
    Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
        modecheck()
    End Sub

    Private Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
        modecheck()
    End Sub

    Private Sub RadioButton2_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton2.CheckedChanged
        modecheck()
    End Sub

    Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged
        modecheck()
    End Sub

    Private Sub RadioButton3_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton3.CheckedChanged
        modecheck()
    End Sub
End Class

```
　(4)「Form1.Designer.vb」(Ver1.2)

```
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Windows フォーム デザイナーで必要です。
    Private components As System.ComponentModel.IContainer

    'メモ: 以下のプロシージャは Windows フォーム デザイナーで必要です。
    'Windows フォーム デザイナーを使用して変更できます。  
    'コード エディターを使って変更しないでください。
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container()
        Me.Text3 = New System.Windows.Forms.TextBox()
        Me.SerialPort1 = New System.IO.Ports.SerialPort(Me.components)
        Me.PictureBox1 = New System.Windows.Forms.PictureBox()
        Me.Button4 = New System.Windows.Forms.Button()
        Me.CheckBox1 = New System.Windows.Forms.CheckBox()
        Me.text1 = New System.Windows.Forms.TextBox()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.Button2 = New System.Windows.Forms.Button()
        Me.text2 = New System.Windows.Forms.TextBox()
        Me.Button5 = New System.Windows.Forms.Button()
        Me.CheckBox2 = New System.Windows.Forms.CheckBox()
        Me.RadioButton1 = New System.Windows.Forms.RadioButton()
        Me.RadioButton2 = New System.Windows.Forms.RadioButton()
        Me.RadioButton3 = New System.Windows.Forms.RadioButton()
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'Text3
        '
        Me.Text3.Font = New System.Drawing.Font("ＭＳ ゴシック", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(128, Byte))
        Me.Text3.Location = New System.Drawing.Point(240, 8)
        Me.Text3.Multiline = True
        Me.Text3.Name = "Text3"
        Me.Text3.Size = New System.Drawing.Size(79, 22)
        Me.Text3.TabIndex = 2
        '
        'SerialPort1
        '
        Me.SerialPort1.BaudRate = 115200
        Me.SerialPort1.PortName = "COM8"
        '
        'PictureBox1
        '
        Me.PictureBox1.Location = New System.Drawing.Point(10, 74)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(640, 480)
        Me.PictureBox1.TabIndex = 7
        Me.PictureBox1.TabStop = False
        '
        'Button4
        '
        Me.Button4.Location = New System.Drawing.Point(186, 40)
        Me.Button4.Name = "Button4"
        Me.Button4.Size = New System.Drawing.Size(41, 28)
        Me.Button4.TabIndex = 8
        Me.Button4.Text = "disp"
        Me.Button4.UseVisualStyleBackColor = True
        '
        'CheckBox1
        '
        Me.CheckBox1.AutoSize = True
        Me.CheckBox1.Location = New System.Drawing.Point(71, 11)
        Me.CheckBox1.Name = "CheckBox1"
        Me.CheckBox1.Size = New System.Drawing.Size(51, 16)
        Me.CheckBox1.TabIndex = 9
        Me.CheckBox1.Text = "Color"
        Me.CheckBox1.UseVisualStyleBackColor = True
        '
        'text1
        '
        Me.text1.Location = New System.Drawing.Point(233, 45)
        Me.text1.Name = "text1"
        Me.text1.Size = New System.Drawing.Size(42, 19)
        Me.text1.TabIndex = 10
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(281, 41)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(38, 23)
        Me.Button1.TabIndex = 11
        Me.Button1.Text = "send"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(122, 5)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(53, 28)
        Me.Button2.TabIndex = 12
        Me.Button2.Text = "capcure"
        Me.Button2.UseVisualStyleBackColor = True
        '
        'text2
        '
        Me.text2.Location = New System.Drawing.Point(187, 10)
        Me.text2.Name = "text2"
        Me.text2.Size = New System.Drawing.Size(47, 19)
        Me.text2.TabIndex = 13
        Me.text2.Text = "COM1"
        '
        'Button5
        '
        Me.Button5.Location = New System.Drawing.Point(122, 41)
        Me.Button5.Name = "Button5"
        Me.Button5.Size = New System.Drawing.Size(53, 27)
        Me.Button5.TabIndex = 14
        Me.Button5.Text = "repeat"
        Me.Button5.UseVisualStyleBackColor = True
        '
        'CheckBox2
        '
        Me.CheckBox2.AutoSize = True
        Me.CheckBox2.Location = New System.Drawing.Point(71, 33)
        Me.CheckBox2.Name = "CheckBox2"
        Me.CheckBox2.Size = New System.Drawing.Size(46, 16)
        Me.CheckBox2.TabIndex = 15
        Me.CheckBox2.Text = "SPD"
        Me.CheckBox2.UseVisualStyleBackColor = True
        '
        'RadioButton1
        '
        Me.RadioButton1.AutoSize = True
        Me.RadioButton1.Location = New System.Drawing.Point(10, 11)
        Me.RadioButton1.Name = "RadioButton1"
        Me.RadioButton1.Size = New System.Drawing.Size(47, 16)
        Me.RadioButton1.TabIndex = 16
        Me.RadioButton1.Text = "VGA"
        Me.RadioButton1.UseVisualStyleBackColor = True
        '
        'RadioButton2
        '
        Me.RadioButton2.AutoSize = True
        Me.RadioButton2.Checked = True
        Me.RadioButton2.Location = New System.Drawing.Point(10, 33)
        Me.RadioButton2.Name = "RadioButton2"
        Me.RadioButton2.Size = New System.Drawing.Size(55, 16)
        Me.RadioButton2.TabIndex = 17
        Me.RadioButton2.TabStop = True
        Me.RadioButton2.Text = "QVGA"
        Me.RadioButton2.UseVisualStyleBackColor = True
        '
        'RadioButton3
        '
        Me.RadioButton3.AutoSize = True
        Me.RadioButton3.Location = New System.Drawing.Point(10, 52)
        Me.RadioButton3.Name = "RadioButton3"
        Me.RadioButton3.Size = New System.Drawing.Size(63, 16)
        Me.RadioButton3.TabIndex = 18
        Me.RadioButton3.Text = "QQVGA"
        Me.RadioButton3.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(663, 554)
        Me.Controls.Add(Me.Text3)
        Me.Controls.Add(Me.RadioButton3)
        Me.Controls.Add(Me.RadioButton2)
        Me.Controls.Add(Me.RadioButton1)
        Me.Controls.Add(Me.CheckBox1)
        Me.Controls.Add(Me.CheckBox2)
        Me.Controls.Add(Me.Button5)
        Me.Controls.Add(Me.text2)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.text1)
        Me.Controls.Add(Me.Button4)
        Me.Controls.Add(Me.PictureBox1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        CType(Me.PictureBox1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub
    Friend WithEvents Text3 As System.Windows.Forms.TextBox
    Friend WithEvents SerialPort1 As System.IO.Ports.SerialPort
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents Button4 As System.Windows.Forms.Button
    Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
    Friend WithEvents text1 As System.Windows.Forms.TextBox
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents text2 As System.Windows.Forms.TextBox
    Friend WithEvents Button5 As System.Windows.Forms.Button
    Friend WithEvents CheckBox2 As System.Windows.Forms.CheckBox
    Friend WithEvents RadioButton1 As System.Windows.Forms.RadioButton
    Friend WithEvents RadioButton2 As System.Windows.Forms.RadioButton
    Friend WithEvents RadioButton3 As System.Windows.Forms.RadioButton

End Class
```
## その他
　上記記載のハード、ソフトは無保証であり、各自の責任においてご利用願います。
　※上記ソフトで、デバックモードでの実行ではプチフリーズする現象が発生しました。
　　また、受信割り込み処理の中にブレーク停止してステップ実行させたときに、OS(windows10)を巻き込んでクラッシュしました。
　　この現象は実行形式(EXE)では発生しておりません。
　　クラッシュ時のMEMORY.DMPより、ドライバ(CH341S64.SYS)に不具合が有ることは確実なので、同環境の場合は動作に注意の事。