Things used in this project

Hardware components:
0zf94dmikia4ydwgeto9
Digilent Zybo
×1
Digilent Pmod COLOR
×1
Software apps and online services:
Xilinx Vivado Webpack

Code

ZYNQ PS main.cC/C++
This file is used to control the Zybo side of the project. It returns RGB data in plain text whenever requested over the UART serial port.
/******************************************************************************/
/*                                                                            */
/* main.c -- Example program using the PmodCOLOR IP                           */
/*                                                                            */
/******************************************************************************/
/* Author: Arthur Brown                                                       */
/*                                                                            */
/******************************************************************************/
/* File Description:                                                          */
/*                                                                            */
/* This demo prints RGB color information collected from the                  */
/* PmodCOLOR when requested, note that typical baud rate is 115200            */
/*                                                                            */
/******************************************************************************/
/* Revision History:                                                          */
/*                                                                            */
/*    10/10/2017(artvvb): Created                                             */
/*                                                                            */
/******************************************************************************/

#include "xparameters.h"
#include "xil_cache.h"
#include "PmodCOLOR.h"
#include "sleep.h"
#include "xuartps.h"

typedef struct {
	COLOR_Data min, max;
} CalibrationData;

void DemoInitialize();
void DemoRun();
CalibrationData DemoInitCalibrationData(COLOR_Data firstSample);
void DemoCalibrate(COLOR_Data newSample, CalibrationData *calib);
COLOR_Data DemoNormalizeToCalibration(COLOR_Data sample, CalibrationData calib);
void EnableCaches();
void DisableCaches();

PmodCOLOR myDevice; // Pmod COLOR driver device
XUartPs sys; // Zynq PS UART driver device

int main(void)
{
	DemoInitialize();
	DemoRun();
	return 0;
}

void DemoInitialize()
{
  //initialize the UART drivers
  XUartPs_Config *myUartCfgPtr;
  myUartCfgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);
  XUartPs_CfgInitialize(&sys, myUartCfgPtr, myUartCfgPtr->BaseAddress);

  //initialize the Pmod COLOR drivers
	COLOR_Begin(&myDevice, XPAR_PMODCOLOR_0_AXI_LITE_IIC_BASEADDR, XPAR_PMODCOLOR_0_AXI_LITE_GPIO_BASEADDR, 0x29);

  //turn on the Pmod COLOR
	COLOR_SetENABLE(&myDevice, COLOR_REG_ENABLE_PON_MASK);
	usleep(2400);
	COLOR_SetENABLE(&myDevice, COLOR_REG_ENABLE_PON_MASK | COLOR_REG_ENABLE_RGBC_INIT_MASK);
	usleep(2400);
}

void DemoRun()
{
	u8 ID, buf[1];
	int n;
	COLOR_Data data;
	CalibrationData calib;

	xil_printf("Pmod COLOR Demo launched\r\n");

	data = COLOR_GetData(&myDevice);
	calib = DemoInitCalibrationData(data);
	usleep(2400);
	//make sure the Pmod COLOR's LED is turned off
	COLOR_SetLED(&myDevice, 0);

	while (1) {
        n = XUartPs_Recv(&sys, buf, 1);
		if (n != 0 && buf[0] == '?') {
		  // when a question character is received over serial
			data = COLOR_GetData(&myDevice);
			DemoCalibrate(data, &calib);
			data = DemoNormalizeToCalibration(data, calib);
			//capture data from the Pmod COLOR and transmit it over serial
			xil_printf("r=%04x g=%04x b=%04x\r\n",data.r,data.g,data.b);
			usleep(2400);
		}
	}
}

CalibrationData DemoInitCalibrationData(COLOR_Data firstSample)
{
	CalibrationData calib;
	calib.min = firstSample;
	calib.max = firstSample;
	return calib;
}

void DemoCalibrate(COLOR_Data newSample, CalibrationData *calib)
{
	if (newSample.c < calib->min.c) calib->min.c = newSample.c;
	if (newSample.r < calib->min.r) calib->min.r = newSample.r;
	if (newSample.g < calib->min.g) calib->min.g = newSample.g;
	if (newSample.b < calib->min.b) calib->min.b = newSample.b;

	if (newSample.c > calib->max.c) calib->max.c = newSample.c;
	if (newSample.r > calib->max.r) calib->max.r = newSample.r;
	if (newSample.g > calib->max.g) calib->max.g = newSample.g;
	if (newSample.b > calib->max.b) calib->max.b = newSample.b;
}

COLOR_Data DemoNormalizeToCalibration(COLOR_Data sample, CalibrationData calib)
{
	COLOR_Data norm;
	norm.c = (sample.c - calib.min.c) * (0xFFFF / (calib.max.c - calib.min.c));
	norm.r = (sample.r - calib.min.r) * (0xFFFF / (calib.max.r - calib.min.r));
	norm.g = (sample.g - calib.min.g) * (0xFFFF / (calib.max.g - calib.min.g));
	norm.b = (sample.b - calib.min.b) * (0xFFFF / (calib.max.b - calib.min.b));
	return norm;
}
requirements.txtPlain text
This file is used to install the required python libraries. The command 'python -m pip -r requirements.txt' will find these libraries from the internet and install them on your system.
pygame==1.9.3
pyserial==3.3
color_visualizer.pyPython
This script will launch a window that will connect to the Zybo and launch a window that displays the last color received. Run it from the command line and provide it with the port that the Zybo is connected to. On a windows system, this will be some COM#, which can be found using the Device Manager under the Ports (COM & LPT) section.

Note: Not backwards compatible with Python 2.
import pygame
import serial
import sys

if len(sys.argv) < 2:
	print('please provide a port number to connect to (format COM#)')
	sys.exit()

try:
	#try to open the serial port
	ser = serial.Serial(sys.argv[1], 115200)
except serial.serialutil.SerialException:
	print('could not find port %s' % sys.argv[1])
	sys.exit()

#create a 480x480 window
screen = pygame.display.set_mode((480,480))
#register a timer event to fire every 100ms
pygame.time.set_timer(pygame.USEREVENT, 100)

while True:
	#wait until an event fires
	event = pygame.event.wait()
	if event.type == pygame.QUIT:
		#user wants to close the window
		break
	elif event.type == pygame.USEREVENT:
		#timer fired, request some data, and update the display
		ser.write(bytes('?', 'utf-8'))
		s = ser.readline().decode('utf-8')
		color = [0]
		idx = 0
		
		#expected format: 'r=%04x g=%04x b=%04x\r\n'
		color = [s[2:6],s[9:13],s[16:20]]
		#pygame color expects values in the range 0-255, strip off the bottom eight bits of each color channel
		rgb = [int(v,16)>>8 for v in color]

		# fill the screen surface with the received color and update the display
		screen.fill(pygame.Color(rgb[0],rgb[1],rgb[2],255))
		pygame.display.flip()
pygame.quit()

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Add projectSign up / Login