<< return to Pixycam.com

Pixy in SPI mode: how to utilize a CS/SS pin ?

hi,
I’m using Pixy in SPI mode.
Now I want to attach more SPI devices to the header (e.g., a SD card slot).
Now how can I utilize a CS/SS pin for the Pixy ?
what have I to change or to set in either source code or lib?

Hi Helmut,
Take a look here:
http://cmucam.org/projects/cmucam5/wiki/Porting_Guide

thanks!

Rich,
I just read the link you posted. I’ve been using SPI without the CS pin. I don’t believe that option was available when I wrote my software. (By the way, I am using GCC with my Parallax Propeller boards).

To use the SPI with SS mode do I have to install new firmware? If so is there a description of all of the changes in it?

Second “By the way”: I find the bigendian method of data sending by pixy to be useful in trying to use fast SPI.

Third: It would be nice if in future firmware there was an option to have a unique Frame sync word, rather than using a repetition of 0xAA55.

Thanks
Tom

tbh, I don’t understand the answers, they actually don’t explain how to use a CS/SS pin -
SPI is a bus which supports multiple hooked-up devices, but to avoid bus errors and data corruption each single SPI device then will require a unique CS/SS pin. Pixy has a CS/SS pin-out (7) but doesn’t use it so far, what is fine as as a single SPI device but what will fail by multiple SPI devices.

The standard cable has just 6 wires, not 7, and if I plugged a customized 7-wire cable:
+to which Arduino GPIO pin do I have to plug wire 7 then ?+
(the rest still goes to the standard SPI pin header of course, just as before!)

+Next: Where to define wire 7 CS/SS in the Pixy code?+

so again my TOP question, maybe someone can write something more detailed ?
(and please keep stuck to my topic^^)

Helmut Wunder wrote:

hi,
I’m using Pixy in SPI mode.
Now I want to attach more SPI devices to the header (e.g., a SD card slot).
Now how can I utilize a CS/SS pin for the Pixy ?
what have I to change or to set in either source code or lib?

hey,

no answer possible?

or are there any proposals on how to use a SS/CS pin by Pixy driver libs and Pixy software ?

I can only give you limited general help. You should be able to pick any unused go pin on the Arduino as the slave select pin. Then in your software, before each data transfer set that pin low. After the transfer set it high to deselect the pixy. I assume that those high / low commands could be added to the example software in the wiki at each data transfer.

There appear to be a number of complications with the new version of pixy SPI that I don’t understand yet, such as having to send sync bytes back to the pixy. For that reason and since I have simple SPI working, I haven’t updated the firmware yet.

I hope this is enough to get started.

Tom

In the first line above “go pin” should be “gpio pin”. Auto spell changed it.

Tom

thank you, but I have no idea how (i.e., WHERE) to set pins high or low.
Given that I’m using dpin 49 as CS/SS -
#define PixyCSPin 49

how / where should I do this

digitalWrite(PixyCSPin , HIGH)
digitalWrite(PixyCSPin , LOW)

in my following code?

// pixy-cam LCDTFT monitoring program
// pixyTFTSPI
// Pixy Cam connected by SPI
// version 0008

#include  
#include 
#include 

// UTFT myGLCD(Model,SDA,SCL,CS,RST,RS)
// adjust the model parameter to suit the display module!
UTFT     myGLCD(QD220A,43,42,41,0,40); 
extern   uint8_t   SmallFont[];
uint8_t    ScrRatio;


Pixy pixy;

void setup()
{

  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);
 
  pixy.init();
  //pixy.blocks[i].x The x location of the center of the detected object (0 to 319)
  //pixy.blocks[i].y The y location of the center of the detected object (0 to 199)
  // Pixy_maxSize/(GLCD_maxSize-frame)
  ScrRatio=max(320/(myGLCD.getDisplayXSize()-20), 200/(myGLCD.getDisplayYSize()-20) )+1;
 
  myGLCD.clrScr(); 
  Serial.begin(19200);
 
}

uint16_t sigcolor( uint8_t signature) {  // <<<<<<<<<<<<<<< customize !! <<<<<<<<<<
  uint16_t color;
  if(signature==1) color=VGA_RED;      // light red
  else
  if(signature==2) color=VGA_AQUA;     // light blue
  else
  if(signature==3) color=VGA_YELLOW;   // just yellow ;)
  else
  if(signature==4) color=VGA_LIME;     // light green
  else
  if(signature==5) color=VGA_FUCHSIA;  // light pink 
  else
  if(signature==6) color=VGA_BLUE;     // dark blue
  else
  if(signature==7) color=VGA_PURPLE;   // dark pink
  else
  color=VGA_WHITE;
  return color;
}
 

char sbuf[240];
#define maxblocks  64
uint8_t    blockS[maxblocks];
uint8_t    blockX[maxblocks];
uint8_t    blockY[maxblocks];
uint8_t    blockW[maxblocks];
uint8_t    blockH[maxblocks];

void loop()
{
  static int i = 0;
  int j;
  uint16_t   nblocks;
  uint8_t    x1,y1,x2,y2; 
 
 
  nblocks = pixy.getBlocks();
 
  if (nblocks)
  {
    i++;
   
    if (i % 10==0)
    {
      myGLCD.clrScr();
      sprintf(sbuf, "Detected %d:\n", nblocks);
      Serial.print(sbuf);
      for (j=0; j<min(nblocks,maxblocks); j++)
      {       
       
        sprintf(sbuf, "  block %d: ", j);
        Serial.print(sbuf);
        pixy.blocks[j].print();   
               
        blockS[j]= pixy.blocks[j].signature;
        blockX[j]= pixy.blocks[j].x;
        blockY[j]= pixy.blocks[j].y;
        blockW[j]= pixy.blocks[j].width;
        blockH[j]= pixy.blocks[j].height;
       
        myGLCD.setColor(sigcolor(blockS[j])); myGLCD.setBackColor(VGA_BLACK);
        x1=blockX[j]-blockW[j]/2;
        x2=blockX[j]+blockW[j]/2;
        y1=blockY[j]-blockH[j]/2;
        y2=blockY[j]+blockH[j]/2;
        myGLCD.drawRect(x1/ScrRatio, y1/ScrRatio, x2/ScrRatio, y2/ScrRatio );
       
        sprintf(sbuf, "%d", blockS[j]); 
        myGLCD.print(sbuf, (x1+10)/ScrRatio,(y1+10)/ScrRatio);
       
      }
    }
  } 
}

Hi Tom,
You’re correct – the new firmware supports SPI withh slave select.

Agreed about the special sync word for a frame — we’re considering this (but we don’t want to break anyone’s existing code!) What platform are you using to talk to your Pixy?

thanks!

Hi Helmut,
There is a new file in the Arduino library called PixySPI_SS.h which is a good place to start if you want to talk to multiple Pixys over SPI. It’s in the latest arduino package http://cmucam.org/attachments/download/1125/arduino_pixy-0.1.6.zip

Since SPI with slave select doesn’t use a standard connector with Arduino (SS pin is different, depending on which ARduino you’re using and if you’re using multiple SS pins… it gets more complicated), you are going to need to modify this code — in the getWord() routine there are 2 digitalWrite calls — one to drive SS low and one to drive SS high. You need to insert/change which slave select pin you’re using.

Note, this is more complicated/advanced. Getting this to work is fairly simple for someone with a background in embedded systems, and/or it requires some good understanding of the existing C code.

thanks!

hey,
I just had a look at the new zip file.

1st, I encountered that you are using a SPI clock devider of 84 for ARM.
This is strange IMO, standard for ARM is 21 which supposed to be 4 MHz which is SPI standard.
Attaching more than just Pixys (e.g., displays and SD card) would slow down data transmission too far.

2nd, I have no idea about how to use
getWord()
getByte()
send()

I’m a hobby home programmer, no computer scientist or a professional embedded C programmer.
So I need simple and intuitive libs and examples.
I just want to poll the pixy frames like in the old hello_world example.

So what I need is a pixy lib where I just have to set


#define PixyCSPin 49 // or whatever

setPixyCSMode(PixyCSPin);

maybe one would need more functions to read multiple Pixys, e.g. by function overloading and by passing the CS/SS pin additionally by

 nblocks = pixy.getBlocks(PixyCSPin);

… and everything will be running fine just like now by my code I posted above.

But anyway, please provide us with appropriate examples for this CS/SS pin mode, please.
The only example file for SPI is hello_world.ino, and that’s just as poor as before.
(BTW, I’m curious why you called it “hello_world.ino” and not “Pixy_SPI.ino”, finally this is what’s it’s actually about… :-/ )

Rich LeGrand wrote:

Hi Tom,
You’re correct – the new firmware supports SPI withh slave select.

Agreed about the special sync word for a frame — we’re considering this (but we don’t want to break anyone’s existing code!) What platform are you using to talk to your Pixy?

thanks!

Rich,

I’ll make this quick so as not to hijack the thread. I am using the Parallax Propeller 8 core micro. The board I am using is the Parallax Activity Board. I’m programming in C with some ASM for high speed SPI. I’ve used your libraries to get a feel for how to interface to pixy, but have written my own code to take advantage of the Propeller C libraries. I have used the pixy ADC and UART modes successfully, but will use SPI to get more data blocks per frame. I have SPI programmed for pixy using the old method, and am considering using the new SPI SS mode.

Tom

Helmut,

I hijacked your thread…

You were asking about an Arduino DUE example with a 4MHz SPI interface.

I would recommend checking out the Arduino example here:

@pixy/src/host/arduino/libraries/Pixy/examples/hello_world@

This page explains how the Arduino clock divider works:

http://arduino.cc/en/Reference/SPISetClockDivider

Thanks,
John

bump

now how should I change my code in order to make it work with a SPI SS/CS pin?
e.g. if I want to use Dpin 49 as the SS/CS pin?

(The question is not about clock devider !)

This is my code I want to adjust for a CS/SS pin:

// pixy-cam LCDTFT monitoring program
// pixyTFTSPI
// Pixy Cam connected by SPI
// version 0008

#include  
#include 
#include 

// UTFT myGLCD(Model,SDA,SCL,CS,RST,RS)
// adjust the model parameter to suit the display module!
UTFT     myGLCD(QD220A,43,42,41,0,40); 
extern   uint8_t   SmallFont[];
uint8_t    ScrRatio;

Pixy pixy;

void setup()
{

  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);

  pixy.init();
  //pixy.blocks[i].x The x location of the center of the detected object (0 to 319)
  //pixy.blocks[i].y The y location of the center of the detected object (0 to 199)
  // Pixy_maxSize/(GLCD_maxSize-frame)
  ScrRatio=max(320/(myGLCD.getDisplayXSize()-20), 200/(myGLCD.getDisplayYSize()-20) )+1;

  myGLCD.clrScr(); 
  Serial.begin(19200);

}

uint16_t sigcolor( uint8_t signature) {  // <<<<<<<<<<<<<<< customize !! <<<<<<<<<<
  uint16_t color;
  if(signature==1) color=VGA_RED;      // light red
  else
  if(signature==2) color=VGA_AQUA;     // light blue
  else
  if(signature==3) color=VGA_YELLOW;   // just yellow ;)
  else
  if(signature==4) color=VGA_LIME;     // light green
  else
  if(signature==5) color=VGA_FUCHSIA;  // light pink 
  else
  if(signature==6) color=VGA_BLUE;     // dark blue
  else
  if(signature==7) color=VGA_PURPLE;   // dark pink
  else
  color=VGA_WHITE;
  return color;
}

char sbuf[240];
#define maxblocks  64
uint8_t    blockS[maxblocks];
uint8_t    blockX[maxblocks];
uint8_t    blockY[maxblocks];
uint8_t    blockW[maxblocks];
uint8_t    blockH[maxblocks];

void loop()
{
  static int i = 0;
  int j;
  uint16_t   nblocks;
  uint8_t    x1,y1,x2,y2; 

  nblocks = pixy.getBlocks();

  if (nblocks)
  {
    i++;

    if (i % 10==0)
    {
      myGLCD.clrScr();
      sprintf(sbuf, "Detected %d:\n", nblocks);
      Serial.print(sbuf);
      for (j=0; j<min(nblocks,maxblocks); j++)
      {       

        sprintf(sbuf, "  block %d: ", j);
        Serial.print(sbuf);
        pixy.blocks[j].print();   

        blockS[j]= pixy.blocks[j].signature;
        blockX[j]= pixy.blocks[j].x;
        blockY[j]= pixy.blocks[j].y;
        blockW[j]= pixy.blocks[j].width;
        blockH[j]= pixy.blocks[j].height;

        myGLCD.setColor(sigcolor(blockS[j])); myGLCD.setBackColor(VGA_BLACK);
        x1=blockX[j]-blockW[j]/2;
        x2=blockX[j]+blockW[j]/2;
        y1=blockY[j]-blockH[j]/2;
        y2=blockY[j]+blockH[j]/2;
        myGLCD.drawRect(x1/ScrRatio, y1/ScrRatio, x2/ScrRatio, y2/ScrRatio );

        sprintf(sbuf, "%d", blockS[j]); 
        myGLCD.print(sbuf, (x1+10)/ScrRatio,(y1+10)/ScrRatio);

      }
    }
  } 
}

Helmut, you are asking us to write code for you! Snap out of it man!

Describe what you are trying to do and why you need to use slave select. I had assumed you were trying to talk to multiple Pixys (the only reason I can think of to use SS), but you have since said you that’s not what you’re trying to do… SS adds more programming complexity, and for someone who is struggling with the code, it’s probably not a good path (for now).

the same issue like about the CC thing!

You didn’t provide me with own tutorial source code - so how shall I know how to use it?

I don’t understand anything about what you linked to about SPI SS mode - so just tell me in MY code where I have to define SS pin to make it work!

I already wrote that I want to attach more SPI devices to the bus, e.g. a SD card and a TFT display. SPI is always designed to attach more than just 1 device, just like it’s for I2C! SPI is a BUS !!

Is that so hard to understand ???

Let’s keep things civil, OK? We’re trying our best to understand what you want.

There is a new file in the Arduino library called PixySPI_SS.h which is a good place to start if you want to talk to multiple devices over SPI. It’s in the latest arduino package http://cmucam.org/attachments/download/1125/arduino_pixy-0.1.6.zip

Since SPI with slave select doesn’t use a standard connector with Arduino (Slave select pin is different, depending on which ARduino you’re using and if you’re using multiple SS pins (like you want to do) it gets more complicated)

You are going to need to modify the file PixySPI_SS.h in the Pixy arduino library. In this file in the getWord() routine there are 2 digitalWrite calls — one to drive SS low and one to drive SS high. You need to insert/change which slave select pin you’re using. We can’t write a tutorial for this because each setup is different.

Note, this is more complicated/advanced. Getting this to work is fairly simple for someone with a background in embedded systems, and/or it requires some good understanding of the existing C code.

Having said all this, the code you posted won’t work — you need to use the PixySPI_SS object (the one that you will modify to work with your particular setup, your slave select signal, etc). YOu can’t use the Pixy object (like your code is currently using).

ok, I see it’s far more complicated than I expected it to be and I have honestly no idea how I should do it exactly.
Usually all my SPI devices have a CS/SS pin to select.

Once having defined a SS pin for my SD card
#define SDSSpin 45
everything works fine with the SD card if I process SDSSpin to the SD API functions

The same it’s about my TFT by
#define TFTSSpin 46
for the TFT LCD if I process TFTSSpin to the TFT API functions

Both libs already provide this functionality right from the start, and that’s just the way exeryone would expect it to work for SPI without any need to hack libraries by skills of a professional embedded C++ programmer.

So I would expect you to provide this functionality also right from the start that one will only need to
#define PixySSpin 49
and process PixySSpin to the Pixy API functions to make it work smart on the SPI bus and make all things work as simple as by the hello_world.ino example.

It’s unreasonable and unacceptable that 1 single device occupies a complete bus (which is just 1x available on Arduinos) completely itself alone.
So I would appreciate very much if you updated your API libs to native SPI-SS mode support in a future which one would call “near”.

I agree that we could make the example SPI with slave select code simpler to use.

We’ll incorporate your suggestion in a future release.

thanks! gladly looking foward!
Unfortunately I won’t be able then to use my SD card reader, my TFT and my Pixy simultaneously until then and my robot won’t work at all as it needs both the TFT, the SD memory card and the Pixy all at once.