You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/fi/4-manufacturing/lessons/2-check-fruit-from-device/wio-terminal-camera.md

19 KiB

Tallenna kuva - Wio Terminal

Tässä oppitunnin osassa lisäät kameran Wio Terminaliin ja otat kuvia sillä.

Laitteisto

Wio Terminal tarvitsee kameran.

Kamera, jota käytät, on ArduCam Mini 2MP Plus. Tämä on 2 megapikselin kamera, joka perustuu OV2640-kuvakennoon. Se kommunikoi SPI-liitännän kautta kuvien ottamiseksi ja käyttää I2C:tä anturin konfigurointiin.

Yhdistä kamera

ArduCam ei sisällä Grove-liitintä, vaan se yhdistetään sekä SPI- että I2C-väylään GPIO-pinnien kautta Wio Terminalissa.

Tehtävä - yhdistä kamera

Yhdistä kamera.

ArduCam-anturi

  1. ArduCamin pohjassa olevat pinnit täytyy yhdistää Wio Terminalin GPIO-pinneihin. Jotta oikeat pinnit löytyvät helpommin, kiinnitä Wio Terminalin mukana tuleva GPIO-tarralappu pinneihin:

    Wio Terminal GPIO-tarralapulla

  2. Käytä hyppylankoja ja tee seuraavat liitännät:

    ArduCAM-pinni Wio Terminal -pinni Kuvaus
    CS 24 (SPI_CS) SPI Chip Select
    MOSI 19 (SPI_MOSI) SPI-ohjaimen ulostulo, laitteen sisääntulo
    MISO 21 (SPI_MISO) SPI-ohjaimen sisääntulo, laitteen ulostulo
    SCK 23 (SPI_SCLK) SPI-sarjakello
    GND 6 (GND) Maa - 0V
    VCC 4 (5V) 5V virtalähde
    SDA 3 (I2C1_SDA) I2C-sarjadata
    SCL 5 (I2C1_SCL) I2C-sarjakello

    Wio Terminal yhdistetty ArduCamiin hyppylangoilla

    GND- ja VCC-liitännät tarjoavat 5V virtalähteen ArduCamille. Se toimii 5V:lla, toisin kuin Grove-anturit, jotka toimivat 3V:lla. Tämä virta tulee suoraan USB-C-liitännästä, joka syöttää virtaa laitteelle.

    💁 SPI-liitännässä ArduCamin pinni-merkinnät ja Wio Terminalin pinni-nimet, joita käytetään koodissa, käyttävät edelleen vanhaa nimeämiskäytäntöä. Tämän oppitunnin ohjeet käyttävät uutta nimeämiskäytäntöä, paitsi silloin kun pinni-nimiä käytetään koodissa.

  3. Voit nyt yhdistää Wio Terminalin tietokoneeseesi.

Ohjelmoi laite yhdistämään kameraan

Wio Terminal voidaan nyt ohjelmoida käyttämään liitettyä ArduCAM-kameraa.

Tehtävä - ohjelmoi laite yhdistämään kameraan

  1. Luo uusi Wio Terminal -projekti PlatformIO:ssa. Nimeä projekti fruit-quality-detector. Lisää koodia setup-funktioon sarjaportin konfiguroimiseksi.

  2. Lisää koodia yhdistääksesi WiFiin, ja tallenna WiFi-tunnistetiedot tiedostoon nimeltä config.h. Älä unohda lisätä tarvittavia kirjastoja platformio.ini-tiedostoon.

  3. ArduCam-kirjasto ei ole saatavilla Arduino-kirjastona, joka voidaan asentaa platformio.ini-tiedostosta. Sen sijaan se täytyy asentaa lähdekoodista heidän GitHub-sivultaan. Voit tehdä tämän joko:

  4. Tarvitset vain ArduCAM-kansion tästä koodista. Kopioi koko kansio projektisi lib-kansioon.

    ⚠️ Koko kansio täytyy kopioida, jotta koodi on lib/ArduCam. Älä kopioi vain ArduCam-kansion sisältöä lib-kansioon, vaan kopioi koko kansio.

  5. ArduCam-kirjastokoodi toimii useille kameratyypeille. Käytettävä kameratyyppi konfiguroidaan kääntäjän lipuilla - tämä pitää rakennetun kirjaston mahdollisimman pienenä poistamalla koodin kameroille, joita et käytä. Konfiguroidaksesi kirjaston OV2640-kameralle, lisää seuraava platformio.ini-tiedoston loppuun:

    build_flags =
        -DARDUCAM_SHIELD_V2
        -DOV2640_CAM
    

    Tämä asettaa kaksi kääntäjän lippua:

    • ARDUCAM_SHIELD_V2 kertoo kirjastolle, että kamera on Arduino-laudalla, joka tunnetaan nimellä shield.
    • OV2640_CAM kertoo kirjastolle, että mukaan otetaan vain OV2640-kameran koodi.
  6. Lisää otsikkotiedosto src-kansioon nimeltä camera.h. Tämä sisältää koodin kameran kanssa kommunikointiin. Lisää seuraava koodi tähän tiedostoon:

    #pragma once
    
    #include <ArduCAM.h>
    #include <Wire.h>
    
    class Camera
    {
    public:
        Camera(int format, int image_size) : _arducam(OV2640, PIN_SPI_SS)
        {
            _format = format;
            _image_size = image_size;
        }
    
        bool init()
        {
            // Reset the CPLD
            _arducam.write_reg(0x07, 0x80);
            delay(100);
    
            _arducam.write_reg(0x07, 0x00);
            delay(100);
    
            // Check if the ArduCAM SPI bus is OK
            _arducam.write_reg(ARDUCHIP_TEST1, 0x55);
            if (_arducam.read_reg(ARDUCHIP_TEST1) != 0x55)
            {
                return false;
            }
    
            // Change MCU mode
            _arducam.set_mode(MCU2LCD_MODE);
    
            uint8_t vid, pid;
    
            // Check if the camera module type is OV2640
            _arducam.wrSensorReg8_8(0xff, 0x01);
            _arducam.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
            _arducam.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
            if ((vid != 0x26) && ((pid != 0x41) || (pid != 0x42)))
            {
                return false;
            }
    
            _arducam.set_format(_format);
            _arducam.InitCAM();
            _arducam.OV2640_set_JPEG_size(_image_size);
            _arducam.OV2640_set_Light_Mode(Auto);
            _arducam.OV2640_set_Special_effects(Normal);
            delay(1000);
    
            return true;
        }
    
        void startCapture()
        {
            _arducam.flush_fifo();
            _arducam.clear_fifo_flag();
            _arducam.start_capture();
        }
    
        bool captureReady()
        {
            return _arducam.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK);
        }
    
        bool readImageToBuffer(byte **buffer, uint32_t &buffer_length)
        {
            if (!captureReady()) return false;
    
            // Get the image file length
            uint32_t length = _arducam.read_fifo_length();
            buffer_length = length;
    
            if (length >= MAX_FIFO_SIZE)
            {
                return false;
            }
            if (length == 0)
            {
                return false;
            }
    
            // create the buffer
            byte *buf = new byte[length];
    
            uint8_t temp = 0, temp_last = 0;
            int i = 0;
            uint32_t buffer_pos = 0;
            bool is_header = false;
    
            _arducam.CS_LOW();
            _arducam.set_fifo_burst();
    
            while (length--)
            {
                temp_last = temp;
                temp = SPI.transfer(0x00);
                //Read JPEG data from FIFO
                if ((temp == 0xD9) && (temp_last == 0xFF)) //If find the end ,break while,
                {
                    buf[buffer_pos] = temp;
    
                    buffer_pos++;
                    i++;
    
                    _arducam.CS_HIGH();
                }
                if (is_header == true)
                {
                    //Write image data to buffer if not full
                    if (i < 256)
                    {
                        buf[buffer_pos] = temp;
                        buffer_pos++;
                        i++;
                    }
                    else
                    {
                        _arducam.CS_HIGH();
    
                        i = 0;
                        buf[buffer_pos] = temp;
    
                        buffer_pos++;
                        i++;
    
                        _arducam.CS_LOW();
                        _arducam.set_fifo_burst();
                    }
                }
                else if ((temp == 0xD8) & (temp_last == 0xFF))
                {
                    is_header = true;
    
                    buf[buffer_pos] = temp_last;
                    buffer_pos++;
                    i++;
    
                    buf[buffer_pos] = temp;
                    buffer_pos++;
                    i++;
                }
            }
    
            _arducam.clear_fifo_flag();
    
            _arducam.set_format(_format);
            _arducam.InitCAM();
            _arducam.OV2640_set_JPEG_size(_image_size);
    
            // return the buffer
            *buffer = buf;
        }
    
    private:
        ArduCAM _arducam;
        int _format;
        int _image_size;
    };
    

    Tämä on matalan tason koodi, joka konfiguroi kameran ArduCam-kirjastojen avulla ja hakee kuvat tarvittaessa SPI-väylän kautta. Tämä koodi on hyvin spesifinen ArduCamille, joten sinun ei tarvitse huolehtia sen toiminnasta tässä vaiheessa.

  7. Lisää main.cpp-tiedostoon seuraava koodi muiden include-lausuntojen alle sisällyttääksesi uuden tiedoston ja luodaksesi kameraluokan instanssin:

    #include "camera.h"
    
    Camera camera = Camera(JPEG, OV2640_640x480);
    

    Tämä luo Camera-instanssin, joka tallentaa kuvat JPEG-muodossa resoluutiolla 640x480. Vaikka suurempia resoluutioita tuetaan (jopa 3280x2464), kuvien luokittelu toimii paljon pienemmillä kuvilla (227x227), joten ei ole tarpeen ottaa ja lähettää suurempia kuvia.

  8. Lisää seuraava koodi tämän alle määrittääksesi funktion kameran asettamiseen:

    void setupCamera()
    {
        pinMode(PIN_SPI_SS, OUTPUT);
        digitalWrite(PIN_SPI_SS, HIGH);
    
        Wire.begin();
        SPI.begin();
    
        if (!camera.init())
        {
            Serial.println("Error setting up the camera!");
        }
    }
    

    Tämä setupCamera-funktio aloittaa konfiguroimalla SPI Chip Select -pinnin (PIN_SPI_SS) korkeaksi, tehden Wio Terminalista SPI-ohjaimen. Se käynnistää sitten I2C- ja SPI-väylät. Lopuksi se alustaa kameraluokan, joka konfiguroi kameran anturiasetukset ja varmistaa, että kaikki on kytketty oikein.

  9. Kutsu tätä funktiota setup-funktion lopussa:

    setupCamera();
    
  10. Rakenna ja lataa tämä koodi ja tarkista sarjaportin monitorin tuloste. Jos näet Error setting up the camera!, tarkista johdotukset varmistaaksesi, että kaikki kaapelit yhdistävät oikeat ArduCamin pinnit oikeisiin GPIO-pinneihin Wio Terminalissa ja että kaikki hyppylangat ovat kunnolla kiinni.

Ota kuva

Wio Terminal voidaan nyt ohjelmoida ottamaan kuva, kun painiketta painetaan.

Tehtävä - ota kuva

  1. Mikro-ohjaimet suorittavat koodiasi jatkuvasti, joten ei ole helppoa käynnistää jotain, kuten valokuvan ottamista, ilman reaktiota anturiin. Wio Terminalissa on painikkeita, joten kamera voidaan asettaa käynnistymään yhdellä painikkeista. Lisää seuraava koodi setup-funktion loppuun konfiguroidaksesi C-painikkeen (yksi kolmesta yläpainikkeesta, lähimpänä virtakytkintä).

    C-painike yläosassa, lähimpänä virtakytkintä

    pinMode(WIO_KEY_C, INPUT_PULLUP);
    

    INPUT_PULLUP-tila kääntää syötteen. Esimerkiksi normaalisti painike lähettäisi matalan signaalin, kun sitä ei paineta, ja korkean signaalin, kun sitä painetaan. Kun tila on INPUT_PULLUP, se lähettää korkean signaalin, kun sitä ei paineta, ja matalan signaalin, kun sitä painetaan.

  2. Lisää tyhjä funktio reagoimaan painikkeen painallukseen ennen loop-funktiota:

    void buttonPressed()
    {
    
    }
    
  3. Kutsu tätä funktiota loop-metodissa, kun painiketta painetaan:

    void loop()
    {
        if (digitalRead(WIO_KEY_C) == LOW)
        {
            buttonPressed();
            delay(2000);
        }
    
        delay(200);
    }
    

    Tämä tarkistaa, onko painiketta painettu. Jos painiketta painetaan, kutsutaan buttonPressed-funktiota, ja silmukka viivästyy 2 sekuntia. Tämä antaa aikaa painikkeen vapauttamiselle, jotta pitkä painallus ei rekisteröidy kahdesti.

    💁 Wio Terminalin painike on asetettu INPUT_PULLUP-tilaan, joten se lähettää korkean signaalin, kun sitä ei paineta, ja matalan signaalin, kun sitä painetaan.

  4. Lisää seuraava koodi buttonPressed-funktioon:

    camera.startCapture();
    
    while (!camera.captureReady())
        delay(100);
    
    Serial.println("Image captured");
    
    byte *buffer;
    uint32_t length;
    
    if (camera.readImageToBuffer(&buffer, length))
    {
        Serial.print("Image read to buffer with length ");
        Serial.println(length);
    
        delete(buffer);
    }
    

    Tämä koodi aloittaa kameran kuvauksen kutsumalla startCapture. Kameran laitteisto ei toimi palauttamalla dataa pyynnön yhteydessä, vaan lähetät käskyn aloittaa kuvaus, ja kamera työskentelee taustalla kuvan ottamiseksi, sen muuntamiseksi JPEG-muotoon ja sen tallentamiseksi kameran paikalliseen puskuriin. captureReady-kutsu tarkistaa, onko kuvan ottaminen valmis.

    Kun kuvaus on valmis, kuvatiedot kopioidaan kameran puskurista paikalliseen puskuriin (tavujen taulukkoon) readImageToBuffer-kutsulla. Puskurin pituus lähetetään sitten sarjaportin monitoriin.

  5. Rakenna ja lataa tämä koodi ja tarkista sarjaportin monitorin tuloste. Joka kerta, kun painat C-painiketta, kuva otetaan ja näet kuvan koon sarjaportin monitorissa.

    Connecting to WiFi..
    Connected!
    Image captured
    Image read to buffer with length 9224
    Image captured
    Image read to buffer with length 11272
    

    Eri kuvat ovat eri kokoisia. Ne pakataan JPEG-muotoon, ja JPEG-tiedoston koko tietylle resoluutiolle riippuu siitä, mitä kuvassa on.

💁 Löydät tämän koodin code-camera/wio-terminal -kansiosta.

😀 Olet onnistuneesti ottanut kuvia Wio Terminalilla.

Valinnainen - varmista kameran kuvat SD-kortilla

Helpoin tapa nähdä kameran ottamat kuvat on kirjoittaa ne SD-kortille Wio Terminalissa ja tarkastella niitä tietokoneellasi. Tee tämä vaihe, jos sinulla on ylimääräinen microSD-kortti ja microSD-korttipaikka tietokoneessasi tai adapteri.

Wio Terminal tukee vain enintään 16GB:n microSD-kortteja. Jos sinulla on suurempi SD-kortti, se ei toimi.

Tehtävä - varmista kameran kuvat SD-kortilla

  1. Alusta microSD-kortti FAT32- tai exFAT-muotoon käyttämällä tietokoneesi sovelluksia (Disk Utility macOS:ssä, File Explorer Windowsissa tai komentorivityökaluja Linuxissa).

  2. Aseta microSD-kortti virtakytkimen alapuolella olevaan korttipaikkaan. Varmista, että se menee kokonaan sisään, kunnes se napsahtaa ja pysyy paikallaan. Saatat joutua työntämään sitä kynnen tai ohuen työkalun avulla.

  3. Lisää seuraavat include-lausunnot main.cpp-tiedoston alkuun:

    #include "SD/Seeed_SD.h"
    #include <Seeed_FS.h>
    
  4. Lisää seuraava funktio ennen setup-funktiota:

    void setupSDCard()
    {
        while (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI))
        {
            Serial.println("SD Card Error");
        }
    }
    

    Tämä konfiguroi SD-kortin käyttämällä SPI-väylää.

  5. Kutsu tätä setup-funktiosta:

    setupSDCard();
    
  6. Lisää seuraava koodi buttonPressed-funktion yläpuolelle:

    int fileNum = 1;
    
    void saveToSDCard(byte *buffer, uint32_t length)
    {
        char buff[16];
        sprintf(buff, "%d.jpg", fileNum);
        fileNum++;
    
        File outFile = SD.open(buff, FILE_WRITE );
        outFile.write(buffer, length);
        outFile.close();
    
        Serial.print("Image written to file ");
        Serial.println(buff);
    }
    

    Tämä määrittää globaalin muuttujan tiedostojen laskemiseen. Tätä käytetään kuvatiedoston nimissä, jotta useita kuvia voidaan tallentaa kasvavilla tiedostonimillä - 1.jpg, 2.jpg ja niin edelleen.

    Se määrittää myös saveToSDCard-funktion, joka ottaa tavupuskurin ja puskurin pituuden. Tiedostonimi luodaan tiedostolaskurin avulla, ja laskuria kasvatetaan seuraavaa tiedostoa varten. Puskurin binääridata kirjoitetaan tiedostoon.

  7. Kutsu saveToSDCard-funktiota buttonPressed-funktiosta. Kutsun tulisi olla ennen puskurin poistamista:

    Serial.print("Image read to buffer with length ");
    Serial.println(length);
    
    saveToSDCard(buffer, length);
    
    delete(buffer);
    
  8. Rakenna ja lataa tämä koodi ja tarkista sarjaportin monitorin tuloste. Joka kerta, kun painat C-painiketta, kuva otetaan ja tallennetaan SD-kortille.

    Connecting to WiFi..
    Connected!
    Image captured
    Image read to buffer with length 16392
    Image written to file 1.jpg
    Image captured
    Image read to buffer with length 14344
    Image written to file 2.jpg
    
  9. Sammuta microSD-kortti ja poista se painamalla sitä hieman sisään ja vapauttamalla, jolloin se ponnahtaa ulos. Saatat joutua käyttämään ohutta työkalua tähän. Liitä microSD-kortti tietokoneeseesi nähdäksesi kuvat.

    Kuva banaanista, otettu ArduCamilla 💁 Kameran valkotasapainon säätämiseen voi kulua muutama kuva. Huomaat tämän kuvien värin perusteella, ensimmäiset kuvat voivat näyttää väriltään poikkeavilta. Voit aina kiertää tämän muuttamalla koodia siten, että setup-funktiossa otetaan muutama kuva, jotka jätetään huomiotta.


Vastuuvapauslauseke:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua Co-op Translator. Vaikka pyrimme tarkkuuteen, huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäinen asiakirja sen alkuperäisellä kielellä tulisi pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa väärinkäsityksistä tai virhetulkinnoista, jotka johtuvat tämän käännöksen käytöstä.