Having a really weird SPI issue.

fastled-support
gplus
(Adam Haile) #1

Having a really weird SPI issue. When I use 1 wire chips like the neopixel (where I use MOSI as the data pin). But when I use SPI chipsets, the program just freezes up when I call FastLED.show()

This is on my own hardware running an ATMega32u4. Anyone ever had it just hang when trying to use SPI?

I’m not sure how it’s a hardware issue or that it is, but for reference, my schematic is below. It worked fine on my mockup with an Arduino Pro Micro but now it doesn’t. As far as I can tell though, all the SPI pins are hooked up just fine. So, this may be out of the scope of this group but I’m totally stumped.

(Adam Haile) #2

Update, if I define FORCE_SOFTWARE_SPI it works. So… something hardware SPI specific?

(Ashley M. Kirchner [Norym]) #3

Everything here looks okay, however that’s neither here nor there. Connections could be missing, labels could be wrong. Just because your schematic shows that something is there, doesn’t necessarily mean it actually is, especially when it comes to junctions. Also, you do not need those resistors on the MOSI/CSK lines. Proper strips will take care of that automatically.

(Adam Haile) #4

I’ve checked all the lines with my meter and everything is actually hooked up where need be. The resistors are there for strips like the WS2812 that in some cases prefer to have them… adafruit suggests it. That’s why the jumpers are there. The resistors are just in case it’s needed (I’m not using them). Wondering if it’s a signal interference issue… since bitbang works (which I’m assuming is slower) but hardware SPI doesn’t. I just realized my CLK line is under the chip… maybe that’s it?

(Adam Haile) #5

Side note… if I connect my LED strip to it while it’s running (I know, probably shouldn’t) the board reboots. Didn’t do that on my mockup with a pro micro.

(Ashley M. Kirchner [Norym]) #6

That’s a good indication that you have a problem with the (custom) board. While you should never do that, at the same time it should not kill the board like that.

(Adam Haile) #7

Yeah. I agree. Working on tracking that down…
Though more info for thought… I tested it with the LPD8806 library here: https://github.com/adafruit/LPD8806 And it works fine with hardware SPI.
Maybe there’s something a little non-standard that FastLED is doing??

(Adam Haile) #8

Actually, the reboot turned out to be an issue of sudden current draw dropping the voltage. There was an “optional” 1000uF cap on the new board that I had neglected to install :stuck_out_tongue: It doesn’t reboot now.

(Ashley M. Kirchner [Norym]) #9

So my statement is correct: a problem with the board. However, I’ve designed many a boards specifically for driving LEDs and I’ve never had that problem, nor do I add a large cap like that to my designs. It’s all in the design of the board, specifically how you’re routing power (and what is it coming out of.)

(Adam Haile) #10

Well, sort of. But an unrelated problem most likely. I had the cap on the older mockup… once I removed it, it happened there too. But that board DOES work with hardware SPI. Normally the LEDs would be powered by the barrel jack on my custom board but I have a jumper to USB power just for testing a few LEDs. When powered from USB was when it rebooted. And I had the brownout set a bit to high. Once I tweaked that it wouldn’t reboot even without the cap.

The fact still remains though that I can run hardware SPI with the arduino libraries but not with FastLED. Are their SPI implementation really that different? I admit, it’s odd that I can run it with hardware SPI on my Arduino Pro Micro based circuit but every test I do shows that SPI does work on my custom board (heck, I’m uploading all my code via ICSP and have no bootloader).

Beginning to wonder if it’s a bad chip…

(Ashley M. Kirchner [Norym]) #11

ICSP is NOT SPI. Uploading using ICSP does not do anything with SPI. Let’s not confuse that.

Stick an SPI card reader on it and see if that works.

(Adam Haile) #12

Fair enough. Mostly just meant that the MOSI, SCLK, MISO pins were clearly properly connected.
I was actually just trying a few other SPI devices (OLED display, RTC, LED matrix… don’t have a card reader) and somewhat frustratingly they work fine. hardware SPI or not. It just seems to be FastLED.

(Ashley M. Kirchner [Norym]) #13

I’m going to assume that you have determined that it does freeze up, and not running but not displaying anything. If that’s the case, and after you post what LED driver you’re using and posting your code, maybe either Dan or Mark can spot an issue. If it’s just code, maybe someone else can also spot the issue.

(Adam Haile) #14

You are correct. I am communicating with it via Serial and when I try to use an SPI driver it never gets to any Serial.write() statements after FastLED.show() . And I cannot communicate with it again until I reboot the board. Code is below. Note that SPI fails but WS2812 does work just fine.

#include “FastLED.h”
#include <EEPROM.h>
#include “global.h”
#include “SPI.h”

CRGB * _fastLEDs;

uint16_t numLEDs = 1;
CLEDController * pLed = NULL;

inline void setupFastLED()
{
_fastLEDs = (CRGB*)malloc(sizeof(CRGB)*numLEDs);
memset(_fastLEDs, 0, sizeof(CRGB)*numLEDs);

switch (config.type)
{
//SPI Based Chipsets
case LEDTYPE::LPD8806:
	pLed = new LPD8806Controller < SPI_DATA, SPI_CLOCK, RGB>();
	break;
case LEDTYPE::WS2801:
	pLed = new WS2801Controller<SPI_DATA, SPI_CLOCK, RGB>();
	break;
//One Wire Chipsets
case LEDTYPE::NEOPIXEL:
	pLed = new WS2811Controller800Khz<ONEWIREPIN, RGB>();
	break;
case LEDTYPE::WS2811_400:
	pLed = new WS2811Controller400Khz<ONEWIREPIN, RGB>();
	break;
default:
	//TODO: Some error condition should go here
	break;
}

if (pLed)
{
	FastLED.addLeds(pLed, _fastLEDs, numLEDs);
}

FastLED.clear();
FastLED.show();

}

void setup()
{
digitalWrite(rebootPin, LOW);
pinMode(rebootPin, OUTPUT);

Serial.begin(115200); //USB Serial, not actually 115200
Serial.setTimeout(1000);

if (EEPROM.read(0) != CONFIGCHECK)
{
	EEPROM.write(0, CONFIGCHECK);
	writeDefaultConfig();
}

readConfig();
numLEDs = config.pixelCount;

setupFastLED();

}

inline void getData()
{
static char cmd = 0;
static uint16_t size = 0;
static uint16_t count = 0;
static size_t c = 0;
static uint16_t packSize = numLEDs * 3; //This will need to be dynamic for other bit depths

if (Serial.available())
{
	cmd = Serial.read();
	size = 0;
	Serial.readBytes((char*)&size, 2);

	if (cmd == CMDTYPE::PIXEL_DATA)
	{
		count = 0;
		if (size == packSize)
		{
			while (count < packSize - 1)
			{
				//should limit the number of 0 responses allow so that it fails out eventually
				c = Serial.readBytes(((char*)_fastLEDs) + count, packSize - count);
				//if (c == 0) break;
				count += c;
			}
		}

		uint8_t resp = RETURN_CODES::SUCCESS;
		if (count == packSize)
		{
			FastLED.show();
		}
		else
			resp = RETURN_CODES::ERROR_SIZE;
		
		Serial.write(resp);
	}

	Serial.flush();
}

}

void loop()
{
getData();
}

(Adam Haile) #15

Fixed it… The pro micro I was using had a resistor and LED between PB0 (SS) and VCC. According to the datasheet, that pin if set as an input needs to be pulled to VCC for SPI to work. So the Pro Micro was doing this already. I didn’t think anything of it because it was just an LED.

The reason the built in SPI class worked is that in its begin() method it calls pinMode(SS, OUTPUT); which is basically what I had to do to fix it. See more here: https://github.com/arduino/Arduino/blob/master/libraries/SPI/SPI.cpp

It seems that FastLED does not do this, at least in the 2.0 branch. Might be a good ideal to add that in?

(Ashley M. Kirchner [Norym]) #16

It may be the way in which you are using the library. I haven’t had to specifically pull that pin up any time I’ve written any code which included FastLED.