Operácie

Triedenie lentiliek: Rozdiel medzi revíziami

Z SensorWiki

(Color sensor)
(Color sensor)
Riadok 29: Riadok 29:
  
 
=== Color sensor ===
 
=== Color sensor ===
 +
 +
Ak chceme aj zobrazenie na displeji, pozri [[LCD displej]]
  
  

Verzia zo dňa a času 18:11, 18. marec 2023

Lentilky.jpg

The seven cartoon "spokescandies" for M&M's since 2022

Lentilky sú obvykle čokoládové alebo ovocné cukríky v tvare šošovky (franc. lentille, angl. lentil) s rôznofarebnoou cukrovou krustou na povrchu. V Česku ich vyrábala firma Sfinx Holešov už od roku 1907 (konkurenčné M&M's sa vyrábajú až od r. 1941). Unikátny výrobný proces českých lentiliek trvá viac ako osem hodín. Firma Sfinx sa v roku 1992 stala súčasťou koncernu Nestlé, čo žiaľ znamenalo aj koniec Lentiliek, pretože od apríla 2021 prevzala výrobu továreň v Hamburgu a to jednak z ekologických dôvodov, ako aj z dôvodu „harmonizácie“ (= zjednotenie receptúry) so značkou Smarties.

Na toto cvičenie si musíte zaobstarať niektoré z týchto cukríkov:


Knižnica ColorPAL


Postup inštalácie (ak ešte nie je na počítači knižnica nainštalovaná):

1. Choďte na nižsieuvedenú stránku, kliknite na zelené tlačítko Code (vpravo hore), z rozbaľovacieho menu si vyberte Download ZIP...

 https://github.com/westpoint-robotics/ColorPAL

2. Po nahratí rozbaľte ColorPAL-master.zip a vyberte folder ColorPAL (bez prípony '-master'). Presu+nte ho do adresára

C:\Users\USername\Documents\Arduino\libraries

3. Reštartujte Arduino IDE a knižnica by mala byť pridaná.


Color sensor

Ak chceme aj zobrazenie na displeji, pozri LCD displej


Senzorov na snímanie farieb je viacero, my sa budeme zaoberať snímačom ColorPAL.

Parallax ColorPAL module contains TAOS TSL12T photodiode with integrated Q/U converter.

TSL12 Schematic.png

Following text will show You a basic connection and operation of the Parallax ColorPal digital colour sensor module.

Parallax ColorPal.jpg

Product page: #28380 ColorPAL

Schematic diagram:

Parallax ColorPAL Schematic.png

Demo program:

/*====================================================
/ Connect ColorPAL SIG signal to Arduino pin 2 and 3
/ Add 2K pullup resistor from pins 2 & 3 to +5v
/ See the result on the serial terminal, 
/ Baud Rate = 115200 kbps  
/ Works with Arduino 0.20, not with 1.00 and above? 
/ Source: http://be470merchantuy.blogspot.com/2012/02/lab-3-serialread-and-colorpal.html
/====================================================*/

#include <SoftwareSerial.h>
SoftwareSerial ColorPAL(2, 3); // rx = 2, tx = 3

int red, grn, blu;

int gotcolor = 0;
int letter;

int redBlackRef=8;
int redWhiteRef=234;

int grnBlackRef=3;
int grnWhiteRef=166;

int bluBlackRef=6;
int bluWhiteRef=285;


void setup(){

Serial.begin(115200); // Start communication with serial port read value
ColorPAL.begin(4800); // Send signal to led to read value

pinMode(2,INPUT); // serial pin out from color pal
pinMode(3,INPUT); // from same serial pin, signal pulls up, sends, pulls down, reads
digitalWrite(2,HIGH); // Enable the pull-up resistor
digitalWrite(3,HIGH); // Enable the pull-up resistor

pinMode(2,OUTPUT); // send signal out
pinMode(3,OUTPUT);
digitalWrite(2,LOW); // turn pin off so pin 3 can go high
digitalWrite(3,LOW);

pinMode(2,INPUT); // Input signal to print
pinMode(3,INPUT);

Serial.println("Pass 1");
delay(20);

while( digitalRead(2) != HIGH || digitalRead(3) != HIGH ) {
Serial.println("In the loop");
delay(50);
}

Serial.println("Pass 2");

pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
digitalWrite(2,LOW);
digitalWrite(3,LOW);
delay(100); // spec is 80, but not all ColorPAL units work with 80

pinMode(2,INPUT);
pinMode(3,OUTPUT);
delay(100);

}

// This oscillates back and forth on one wire to turn off led, send signal,
// turn on led, read signal. very fast strobe read - arduino is not capable of
// one wire signal communication over digital ports, so this is a way around
// that over 2 wires communicating with 1 pin on the sensor.
//---------------------------------

void loop()
{
 
  readColor();

  int redCorrect = (255*(red-redBlackRef))/(redWhiteRef-redBlackRef);
  int bluCorrect = (255*(blu-bluBlackRef))/(bluWhiteRef-bluBlackRef);
  int grnCorrect = (255*(grn-grnBlackRef))/(grnWhiteRef-grnBlackRef);


  Serial.print("R");
  Serial.print(redCorrect);
  Serial.print(" ");
  Serial.print(red);
  Serial.print(" G");
  Serial.print(grnCorrect);
  Serial.print(" ");
  Serial.print(grn);
  Serial.print(" B");
  Serial.print(bluCorrect);
  Serial.print(" ");
  Serial.println(blu);

  //int redCorrect = red;
  //int bluCorrect = grn;
  //int grnCorrect = blu;

  if (redCorrect > 240 && redCorrect <=255 && grnCorrect >240 && grnCorrect <=255 && bluCorrect >240 && bluCorrect <= 255)
  {
    Serial.print("White");
    delay(100);
  }


  if (redCorrect > 0 && redCorrect <= 40 && grnCorrect >0 && grnCorrect <=40 && bluCorrect >0 && bluCorrect <= 40){
     Serial.print("Black");
     delay(100);
   }

  if (redCorrect > 140 && redCorrect <= 255 && grnCorrect >0 && grnCorrect <=80 && bluCorrect >0 && bluCorrect <= 130){
     Serial.print("Red");
     delay(100);
   }

  if (redCorrect > 200 && redCorrect <= 255 && grnCorrect >0 && grnCorrect <=200 && bluCorrect >130 && bluCorrect <= 255){
     Serial.print("Pink");
     delay(100);
  }

   if (redCorrect > 200 && redCorrect <= 255 && grnCorrect >80 && grnCorrect <=160 && bluCorrect >0 && bluCorrect <= 120){
     Serial.print("Orange");
     delay(100);
   }

   if (redCorrect > 180 && redCorrect <= 255 && grnCorrect >200 && grnCorrect <=255 && bluCorrect >0 && bluCorrect <= 255){
      Serial.print("Yellow");
      delay(100);
    }

   if (redCorrect > 120 && redCorrect <= 200 && grnCorrect >0 && grnCorrect <=230 && bluCorrect >120 && bluCorrect <= 255){
      Serial.print("Purple");
      delay(100);
    }

   if (redCorrect > 0 && redCorrect <= 180 && grnCorrect >100 && grnCorrect <=255 && bluCorrect >0 && bluCorrect <= 170){
      Serial.print("Green");
      delay(100);
   }

   if (redCorrect > 0 && redCorrect <= 180 && grnCorrect >0 && grnCorrect <=255 && bluCorrect >170 && bluCorrect <= 255){
      Serial.print("Blue");
      delay(100);
   }

  gotcolor = 0;
  delay(100);

}  /* End of loop()  */

/* ***************************************** */
/* Function readColor()                      */
/* Reads ColorPAL, putting results in the    */
/*       red, grn, blu variables             */
/* ***************************************** */
void readColor() 
{ 
  char rByte[9];
  char dummy[4];
  
  delay(20);
  ColorPAL.begin(4800);
  ColorPAL.print("= (00 $ m) !"); // set up loop to continuously send color data
  pinMode(3,INPUT);
  gotcolor = 0;
  while (gotcolor == 0) 
   {
     rByte[0] = ColorPAL.read();
     if( rByte[0] == '$' ) 
      {
       gotcolor = 1;
       for (int i=0; i<9; i++) 
          {
           rByte[i] = ColorPAL.read();
           // Serial.print(rByte[i]);
          }
      Serial.println("");
     dummy[0] = rByte[0];
     dummy[1] = rByte[1];
     dummy[2] = rByte[2];
     dummy[3] = 0;

     red = strtol(dummy,NULL,16);

     dummy[0] = rByte[3];
     dummy[1] = rByte[4];
     dummy[2] = rByte[5];
  
     grn = strtol(dummy,NULL,16);

     dummy[0] = rByte[6];
     dummy[1] = rByte[7];
     dummy[2] = rByte[8];

     blu = strtol(dummy,NULL,16);
    }
   }
}  /* End of function readColor() */

If the program works correctly, it will send to the serial port (115 200 Bd) following data:


R27 32 G106 71 B40 50
Green
R37 41 G134 89 B50 61
Green
R34 39 G126 84 B46 57
Green
R19 25 G84 57 B27 36

R18 24 G78 53 B26 35

R15 22 G65 45 B23 32

R15 22 G68 47 B22 31

R14 21 G68 47 B21 30
R16 23 G31 23 B26 35
Black
R16 23 G32 24 B30 39
Black
R15 22 G26 20 B21 30
Black
R10 17 G21 17 B19 27

Demo software

Following Arduino code works with an original Parallax (or PhiPi) ColorDemo.exe program available at the following address: http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/ColorPAL_programs.zip

ColorPAL demo.png
/*====================================================
/ Connect ColorPAL SIG signal to Arduino pin 2 and 3
/ Baud Rate = 9600 kbps
/ Works with Arduino 0.20, not with 1.00 and above?
/====================================================*/

#include <SoftwareSerial.h>

SoftwareSerial ColorPAL(2, 3); // rx = 2, tx = 3

int red, grn, blu;

int gotcolor = 0;
int letter;

char colorByte[9];

void setup(){

  // for colordemo 9600,
Serial.begin(9600); // Start communication with serial port read value
ColorPAL.begin(4800); // Send signal to led to read value

pinMode(2,INPUT); // serial pin out from color pal
pinMode(3,INPUT); // from same serial pin, signal pulls up, sends, pulls down, reads
digitalWrite(2,HIGH); // Enable the pull-up resistor
digitalWrite(3,HIGH); // Enable the pull-up resistor

pinMode(2,OUTPUT); // send signal out
pinMode(3,OUTPUT);
digitalWrite(2,LOW); // turn pin off so pin 3 can go high
digitalWrite(3,LOW);

pinMode(2,INPUT); // Input signal to print
pinMode(3,INPUT);

delay(20);

while( digitalRead(2) != HIGH || digitalRead(3) != HIGH ) {
delay(50);
}


pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
digitalWrite(2,LOW);
digitalWrite(3,LOW);
delay(100); // spec is 80, but not all ColorPAL units work with 80

pinMode(2,INPUT);
pinMode(3,OUTPUT);
delay(100);


  delay(20);
  ColorPAL.begin(4800);
  ColorPAL.print("= (00 $ m) !"); // set up loop to continuously send color data
  pinMode(3,INPUT);


}

// This oscillates back and forth on one wire to turn off led, send signal,
// turn on led, read signal. very fast strobe read - arduino is not capable of
// one wire signal communication over digital ports, so this is a way around
// that over 2 wires communicating with 1 pin on the sensor.
//---------------------------------

void loop()
{

  readColor();
  gotcolor = 0;
  delay(100);

}  /* End of loop()  */


/* ***************************************** */
/* Function readColor()                      */
/* Reads ColorPAL, putting results in the    */
/*       red, grn, blu variables             */
/* ***************************************** */
void readColor()
{
  char rByte[9];
  char dummy[4];

//  delay(20);
//  ColorPAL.begin(4800);
//  ColorPAL.print("= (00 $ m) !"); // set up loop to continuously send color data

  pinMode(3,INPUT);
  gotcolor = 0;
  while (gotcolor == 0)
   {
     rByte[0] = ColorPAL.read();
     if( rByte[0] == '$' )
      {
       gotcolor = 1;
       for (int i=0; i<9; i++)
          {
           rByte[i] = ColorPAL.read();
          }

     Serial.print("R0");
     Serial.print(rByte[0]);
     Serial.print(rByte[1]);
     Serial.print(rByte[2]);
     Serial.print(" G0");
     Serial.print(rByte[3]);
     Serial.print(rByte[4]);
     Serial.print(rByte[5]);
     Serial.print(" B0");
     Serial.print(rByte[6]);
     Serial.print(rByte[7]);
     Serial.print(rByte[8]);
     Serial.println();     

    }
   }
}  /* End of function readColor() */


Snímač farby ColorPAL

  • Vypracovali:
Bc. Tamás Vincze
Bc. Adam Rozsár
  • Študijný odbor: Aplikovaná mechatronika
  • Ročník: 2.Ing

Zadanie

Zobrazte na LCD aktuálnu snímanú farbu zmeranú snímačom ColorPal.

SnimacFarbyColorPal.jpg

Literatúra:


Snímač a generátor farby ColorPAL

Vlastnosti

  • Sníma celý rozsah farieb o ktorých dáva informáciu vo forme RGB (Red/Green/Blue) komponentov.
  • Sníma spektrum okolitého osvetlenia s citlivosťou až 44uW/cm2 na lsb.
  • Generuje 24 bitové farby pomocou vstavaného RGB LED.
  • Možnosť pripojenia priamo na skúšobnú dosku alebo pomocou predlžovacích káblov.
  • Na detekciu a generovanie farby využíva sériovú komunikáciu cez jeden pin.
  • Detekcia a generovanie farieb je riadené pomocou vstavaného mikrokontrolera.
  • Disponuje vstavanou EEPROM pamäťou pre uloženie snímaných informácií a generačných programov.
  • Autorun funkcia umožňuje spustenie vopred určeného programu iba použitím napájania.

Obr8.jpg

Princíp činnosti

ColorPAL používa RGB LED na osvetlenie meranej farby (jedna farba naraz), spolu so široko spektrovým prevodníkom svetlo-napätie na meranie odrazeného svetla. Podľa množstva svetla ktoré sa odráža od meranej farby pri osvetlení od červenej, zelenej a modrej LED diódy je možné určiť farbu vzorky. ColorPAL používa sveteľný senzor TAOS typu TSL13T, ktorý má krivku spektrálnej citlivosťi nasledovný:

Obr1.png

Obr. 1: Krivka spektrálnej citlivosti prevodníka svetlo-napätie

Prevodník je kombináciou fotodiódy a transimpedančného zosilňovača v jednom integrovanom obvode. Aktívna plocha fotodiódy je 0.5 mm x 0.5 mm a senzor vníma žiarenie s vlnovou dĺžkou v rozsahu od 320 nm do 1050 nm.Výstupné napätie sa mení lineárne s intenzitou dopadajúceho žiarenia.

Obr2.jpg

Obr. 2: Funkčná schéma zapojenie prevodníka

Obr3.jpg

Obr. 3: Pohľad z hora prevodníka

Výstupom snímača je napätie, úmerné celého žiarenia ktoré detekuje a ktoré sú potom merané podľa hore uvedenej krivky spektrálnej citlivosti. Keď predmet je osvetlený iba červenou LED, tak snímač bude reagovať s napätím úmerným červenej zložky z farby predmetu a podobne s modrou a zelenou. Snímač a RGB LED diódy sú umiestnené vedľa seba v jednej plastickej trubice.


Použitie

Senzor používa 3 piny: regulované +5V napájanie, zem a sériový dátový pin s otvoreným kolektorom. Pri práci sme snímač napojili na skúšobnú dosku podľa Obr. 2. Museli sme dávať pozor, aby bol jumper vhodne nastavený, na Vdd a nie na Vin.

Obr2.png

Obr. 4: Schéma zapojenia snímača ColorPAL

Programovanie

Komunikácia s ColorPAL-om je realizovaná cez sériovú linku, prijímanie a odosielanie medzi 2400 a 7200 baudom. ColorPAL má v sebe zabudovaný pullup rezistor, preto nie je potrebné používať externý. Pretože používa open-drain protokol, pin ktorý sa používa na komunikáciu s ColorPAL-om by mal byť vždy nastavený ako vstupný, okrem prípadu keď je v stave 0. Pri inicializovaní snímača musíme čakať aby ColorPAL dal tento pin do jednotky predtým než začneme posielať príkazy.


Snímač môže pracovať v rôznych režimoch:

  • Priamy režim: príkazy sú prijímané a vykonávané ihneď
  • Bufferovací režim: príkazy sú prijímané a uložené do buffera pre použitie v budúcnosti
  • Vykonávací režim: príkazy, ktoré sú uložené do EEPROM pamäte, sa vykonajú


Snímač vieme resetovať tromi rôznymi spôsobmi:

  • Powerup: pri prvom zapnutí ColorPAL začne vykonávať príkazy, ktoré sú uložené vo vnútornej pamäti EEPROM na adrese 00. Pri novom, ešte neprogramovanom snímači tento program prejde do priameho módu.
  • Short Break: 7 milisekundová logická 0 resetuje snímač a začne sa vykonávať Powerup.
  • Long Break: 80< milisekundová logická 0 resetuje snímač a vstúpi do Priameho módu.

Obr20.jpg

Riešenie

Sériová linka používa piny D0 a D1 portu D mikropočítača. LCD panel,ktorý sme na paneli mali vopred zapojený používa tiež PORTD pre komunikáciu, kvôli čomu sme tento LCD modul nevedeli použiť na výpis výsledku merania snímača. Zapojili sme nový LCD modul, ktorý používa PORTB ako riadiacu zbernicu a PORTC ako dátovú zbernicu. Patričné zmeny sme vykonali aj v hlavičkových súboroch:

lcd.c, lcd.h

Presné zapojenie LCD modulu je na Obr.5.

Obr.5.jpg

Obr. 5: Zapojenie LCD modulu

Potrebovali sme pripojiť k projektu ešte ďalšie súbory:serial.c serial.h

Zdrojový kód nášho programu:

#include "lcd.h"
#include "serial.h"
#include <stdio.h>

char sgetc(void)
{
while ((UCSR0A & (1 << RXC0)) == 0)                // Počká kým sú prijaté dáta
	  {
	    //  Nerobí nič, pokiaľ nie sú dáta prijaté a nie je pripravené čítať z UDR
	  }; 
      return UDR0;                               // prijatý bajt sa uloží do UDR0  
}


int main(void)
{
char buffer[9];
inituart();

int i;

FILE mystdout = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE); // "sendchar" je funkcia pre posielanie jedného znaku
		
inituart();                                                           //inicializácia sériovej linky
			_delay_ms(80);
unsigned char znak;
 			_delay_ms(2000);

     lcdInit4();                             // inicializacia v 4-bitovom rezime
     lcdControlWrite(1<<LCD_CLR);            // display clear
     lcdControlWrite(0x40);                  // pozicia 0,0

		lcdDataWrite(znak='A');   
		lcdDataWrite(znak='H');      //testovanie výpisu na LCD panel
		lcdDataWrite(znak='O'); 
		lcdDataWrite(znak='J'); 


 	stdout = &mystdout;           // Odteraz funguje printf();

   	DDRD&=0xF8;		//nastavenie používaných pinov D0,D1 a D2 ako vstupné
	PORTD=0x00;		//bez nastavenia pull-up rezistorov
	
	DDRD|=0x06;             //nastavenie pinov D1 a D2 ako výstupné
	PORTD=0x00;

		_delay_ms(80);  // 80 ms logická nula pre vstup do priameho módu 

	DDRD&=0xFA;             //nastavenie pinu D2 ako vstupný
inituart();

stdout = &mystdout;

/*	printf("=C!");
		_delay_ms(2000);
	printf("=R!");
		_delay_ms(2000);                       //testovanie RGB LED
	printf("=Q!");
		_delay_ms(2000);
	printf("=B!");
		_delay_ms(2000);*/

printf("=(00 @ m )!");                                //posielanie príkazu na opakované meranie-pred výstupný údaj vloží znak "@"
                                                      
DDRD&=0xF8;                                   // nastavenia pinov D0,D1 a D2 ako vstupné                                       
   for (;;)                                         
   {
	while(sgetc()!='@');                          //ak v prijatých dátach sa vyskytne znak "@"
	for(i=0;i<9;i++)                              //uloží nasledujúcich 9 znakov do bufferu
		buffer[i]=sgetc();                      
		lcdControlWrite(0xC0);                //skočí na druhý riadok LCD modulu
	for(i=0;i<9;i++)
		lcdDataWrite(buffer[i]);              //výpis znakov na LCD
	
	}
     for(;;);
     return 0;
}

Počas riešenia úlohy sa nám vyskytol problém že sme sa nevedeli dostať do priameho režimu. Presvedčili sme sa s osciliskopom že na dátovom pine snímača sa nevyskytuje 80 milisekundová log. 0 a preto sa snímač nedostal do požadovaného módu. Použili sme pin D2 portu D pre správne nastavenie log. 0 pre vstup do priameho módu. Posielaním príkazov sme nemali problém cez sériovú linku snímača, RGB LED sme vedeli vysvecovať pomocou LED príkazov podľa datasheet-u. Prijaté dáta sme vedeli zobrazovať len na termináli. Snímač nám vrátil 9 číslicové hexa kódy v tvare @RRRGGGBBB. Tento údaj nám dáva informáciu o tom, v akom pomere sú prítomné jednotlivé zložky (červená, zelená a modrá) žiarenia odrazeného od skúmanej farby. Jednotlivé hexa zložky sme premenili na decimálne hodnoty, ktoré sme potom prepočítali na RGB kód. Pomocou týchto RGB kódov sme prispeli ku grafickému zobrazeniu meranej farby použitím grafického editora. (Obr. 6) Prepočty jednotlivých farieb vidíme v tabulke:

Obr10.jpg


Záver

Vykonali sme pár meraní na týchto farbách s nasledovnými výsledkami:

Obr9.jpg

Obr. 6: Porovnanie reálnych a snímaných farieb so snímačom ColorPAL

Z výsledkov merania je zrejmé že snímač nie je celkom presný. K presnejšiemu meraniu potrebujeme nakalibrovať snímač a použiť korekciu.