I really want to make use of the SPI module on my NodeMCU. SPI keeps my code clean and frees up some of my GPIO pins. I feel it is sending data too fast for my 74HC595 to keep up with. It was working for a bit, then stopped.
It seemed like there was a lot of noise on the line so I hooked up the logic analyzer and saw that when I was sending data, bits were flying across the line at almost 6 ns (which is awesome). I am driving a 595 and ultimately a stepper, that need data at a way slower rate. I have tried using the clock parameter in the setup call, I feel it never slows the SPI clock.
Is there any way to set the clock speed to something that would be more 595+stepper friendly?
Just looking at the docs in the most recent dev branch of NodeMCU (get it from the NodeMCU Build website) you can setup SPI with a divider to lower the data rate of the SPI transmissions (higher div, lower bit rate):
spi.setup(id, mode, cpol, cpha, databits, clock_div[, duplex_mode])
Parameters include:
clock_div - SPI clock divider, f(SPI) = f(CPU) / clock_div
Related
Recently, I bought a Nucleo-144 development board for the STM32F746. For the project I'm working on, I need to get consistent >3 MB/s write speeds to the SD card. Using STM32CubeIDE, I've been able to get SD 1-bit mode working with FatFS in both polling and DMA modes at full speed. However, switching to SD 4-bit mode, I start getting lots of IO errors relating to bad data CRCs while reading.
Details
In SD 4-bit polling mode, I can't even get a single block read to process correctly. Calling f_mount returns an IO error, and debugging it further reveals that the first call to HAL_SD_ReadBlocks, reading sector 0, fails with the error code SDMMC_ERROR_DATA_CRC_FAIL:
Inspecting the 512 byte data buffer it's read to from the card reveals that data is at least partially intact containing some strings you'd expect to see in the first sector:
Importantly, this buffer is corrupted in the exact same manner between each run of the software. If it was some kind of electrical interference problem, I'd expect to see different bytes being corrupted, but I don't. The buffer is identical between runs. Switching back to 1-bit mode and inspecting the data buffer, it's clearly in a lot better shape. The 4-bit buffer clearly has a lot of corrupted bits and bits that are missing entirely, offsetting everything. 4-bit mode is reading mostly junk, but consistently the same junk.
What I've Tried
Polling and DMA mode.
Both fail in a similar manner, although it's harder to debug DMA.
Decreasing the SDMMCCLK clock divider all the way down to 255, the highest divider (and lowest clock speed) it'll go.
On my older, cheaper, Lexar SD card read/writes in this mode work flawlessly (albeit very slowly).
On my newer, more expensive, Samsung SD card read/writes still fail with a SDMMC_ERROR_DATA_CRC_FAIL error. The data buffer appears much more intact, but it's clearly still garbage data.
Transfers with GPIO pull-ups applied to all SD pins (except clock) as well as without pull-ups.
No change, at least as far as I could tell.
Using multiple different SD cards.
Specifically, a Lexar "300x" 32 GB card and a Samsung "EVO Plus" 128 GB card.
As mentioned previously, decreasing the clock speed allowed one of my two cards to work.
However, my higher quality card still fails on the first read even at the minimum speed.
Wiring
Not sure how relevant this is, but figured I'd include it for sake of completion. This is how I have my SD card connected while prototyping. All of the cables are the same length, but perhaps they're interfering with each other even over such a short distance? I'm also using an Adafruit SD card breakout adapter for testing.
SD Card
GPIO Pin
CLK
PC12
D0
PC8
CMD
PD2
D3
PC11
D1
PC9
D2
PC10
Summary
It appears that with some cards, even at lower clock speeds, IO errors are incredibly common in SD 4-bit mode only. At higher clock speeds, all cards I'm able to test with start having IO errors in 4-bit mode. In SD 1-bit mode, however, even at the maximum clock speed I'm able to read and write fine.
I'd like to take advantage of the 4-bit mode for faster speeds. What am I doing wrong? Is it something electrical, like for example needing stronger pull-up resistors or shorter wires? Thanks, I really appreciate it!
I had similar issues on a H743ZI Nucleo. My code worked fine on two other H743 boards with onboard sdcard readers, but failed on the Nucleo with Adafruit breakout. I believe it was just due to signal integrity..
I see you tried dropping the clock divider down, but have you tried a slower SDMMC clock? This was what made the difference for me. Was failing at 48MHz, but fine at 24MHz and lower with 0 divider.
I am trying to learn how to debug an MCU non-intrusively using SWD & openOCD.
while (1)
{
my_count++;
HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
HAL_Delay(750);
}
The code running on my MCU has a free running counter "my_count" . I want to sample/trace the data stored in the address holding "my_count" in real time :
I was doing it this way:
while(1){// generic algorithm no specific language
mdw 0x00000000200000ac; //openOCD command to read from an address
}
0x200000ac is the address of the variable my_count from the .map file.
But, this method is very slow and experiences data drops at high frequencies.
Is there any other way to trace the data at high frequencies without experiencing data drops?
I made some napkin math, and I have an idea that may work.
As per Reference Manual, page 948, the max baud rate for UART of STM32F334 is 9Mbit/s.
If we want to send memory at the specific address, it will be 32 bits. 1 bit takes 1/9Mbps or 1.111*10^(-7)s, multiply that by 32 bits, that makes it 3.555 microseconds. Obviously, as I said, it's purely napkin math. There are start and stop bits involved. But we have a lot of wiggle room. You can easily fit 64 bits into transmission too.
Now, I've checked with the internet, it seems the ST-Link based on STM32F103 can have max baud rate of 4.5Mbps. A bummer, but we simply need to double our timings. 3.55*2 = 7.1us for 32-bit and 14.2us for 64-bit transmission. Even given there is some start and stop bit overhead, we still seem to fit into our 25us time budget.
So the suggestion is the following:
You have a timer set to 25us period that fires an interrupt, that activates DMA UART transmission. That way your MCU actually has very little overhead since DMA will autonomously handle the transmission, while your MCU can do whatever it wants in the meantime. Entering and exiting the timer ISR will be in fact the greatest part of the overhead caused by this, since in the ISR you will literally flip a pair of bits to tell DMA to send stuff over UART # 4.5Mbps.
I'd like to test a SPI slave on my STM32F4 via JTAG boundary scanning methods (best would be using OpenOCD, instead of other special tool).
Does somebody know details and typical pitfalls of such thing?
What I found was this site, whereas this neatly explains boundary scanning.
I am thankful for any hint on that topic.
As the linked site points out, testing your µC's output on the SPI pins through boundary scan will suffer from very low speed (because you have to feed the corresponding bit-banging commands through the boundary-scan protocol, which is far from efficient).
Using the STM32F4 controller, I therefore suggest you to keep the CPU in debug (break), and to set up the GPIOs and SPI through JTAG (as if the firmware were doing this from inside). Then, you are free to put entire data bytes/words into the TX register and poll the SPI status and RX register. This is one or two levels above the (plain) boundary scan method, but it will be quite easy to implement.
(Only) if you want to take this idea even some steps further, you can use JTAG first to switch the clock settings to higher speed or to add DMA (and write larger amounts of data to RAM before triggering the SPI transfer).
Hi Im using the following RF module
http://www.apogeekits.com/rf_receiver_module_rx433.htm
on an embedded board with the PIC16F628A. Sadly, I realized that the signal strength was in analog form and couldn't get any ideas to get the RSSI reading off the pin because well my PIC is digital DUH!.
My basic idea was
To get the RSSI value from my Receiver
Send it to the PIC
Link the PIC to a PC via RS232
Plot a graph of time vs RSSI of the receiver (so I can make out how close my TX is to my RX)
I thought it was bloody brilliant at first but ive hit a dead end here. Any ideas on getting the RSSI data to my PC from this receiver would be nice.
Thanks in Advance
You can get a PIC that has an integrated ADC for sampling the analog signal. Or, you can use an external ADC chip to do the conversion. You would connect that to your PIC using SPI or I2C.
The simplest thing to do is obviously to use a more appropriate microcontroller - one with an ADC! There are many (most), including PICs (though that wouldn't be my first choice).
Attaching an external SPI or I2C ADC might be a bit tedious since having no SPI or I2C on your part, you'd have to bit-bash it. If you do that, use an SPI part - its simpler. Your sample rate will suffer and may end-up being a bit jittery if you are not careful.
Another solution is to use a voltage controlled PWM, then use the timer input capture to time the pulse width. That will give you good regularity and potentially good resolution. You can get a chip (example) to do that, or grow your own. That last option requires a triangle wave input as well as the measured (control) voltage, but on the same site...
In a similar vein, you could use a low frequency VCO (example) and use the output to clock one of the timers, then using a second timer periodically sampling the first and reset it. The count will relate to the voltage, though not necessarily a linear relationship, linearisation could be none on the PIC or at the receiving PC - I'd go for the latter - your micro will suck at arithmetic (performance wise) - even integer arithmetic, especially if it involves division.
I'd like to start out with the Arduino to make something that will (preferably) dim my room lights and turn on some recessed lighting for my computer when a button or switch is activated.
First of all, is this even possible with the Arduino?
Secondly, how would I switch on and off real lights with it? Some sort of relay, maybe?
Does anyone know of a good tutorial or something where at least parts of this are covered? I'll have no problems with the programming, just don't know where to start with hardware.
An alternative (and safer than playing with triacs – trust me I've been shocked by one once and that's enough!) is to use X-10 home automation devices.
There is a PC (RS232) device (CM12U UK or CM11 US) you can get to control the others. You can also get lamp modules that fit between your lamp and the wall outlet which allows you to dim the lamp by sending signals over the mains and switch modules which switch loads on and off.
The Arduino has a TTL level RS232 connector (it's basically what the USB connection uses) – Pins 0 and 1 on the Diecimila so you could use that, connect it via a level converter which you can buy or make and connect to the X-10 controller, theirs instructions on the on the Arduino website for making a RS232 port.
Alternatively you could use something like the FireCracker for X-10 which uses 310MHz (US) or 433MHz (UK) and have your Arduino send out RF signals which the TM12U converts into proper X-10 mains signals for the dimmers etc.
In the US the X-10 modules are really cheep as well (sadly not the case in the UK).
Most people do it using triacs. A triac is like two diodes in anti-parallel (in parallel, but with their polarity reversed) with a trigger pin. A triac conducts current in either direction only when it's triggered. Once triggered, it acts as a regular diode, it continues to conduct until the current drops bellow its threshold.
You can see it as a bi-directional switch on a AC line and can vary the mean current by triggering it in different moments relative to the moment the AC sine-wave crosses zero.
Roughly, it works like this: At the AC sine-wave zero, your diodes turn off and your lamp doesn't get any power. If you trigger the diodes, say, halfway through the sine's swing, you lamp will get half the normal current it would get, so it lights with half of it's power, until the sine-wave crosses zero again. At this point you start over.
If you trigger the triac sooner, your lamp will get current for a longer time interval, glowing brighter. If you trigger your triac latter, your lamp glows fainter.
The same applies to any AC load.
It is almost the same principle of PWM for DC. You turn your current source on and off quicker than your load can react, The amount of time it is turned on is proportional to the current your load will receive.
How do you do that with your arduino?
In simple terms you must first find the zero-crossing of the mains, then you set up a timer/delay and at its end you trigger the triac.
To detect the zero-crossing one normally uses an optocoupler. You connect the led side of the coupler with the mains and the transistor side with the interrupt pin of your arduino.
You can connect your arduino IO pins directly to the triacs' triggers, bu I would use another optocoupler just to be on the safe side.
When the sine-wave approaches zero, you get a pulse on your interrupt pin.
At this interrupt you set up a timer. the longer the timer, the less power your load will get. You also reset your triacs' pins state.
At this timers' interrupt you set your IO pins to trigger the triacs.
Of course you must understand a little about the hardware side so you don't fry your board, and burn your house,
And it goes without saying you must be careful not to kill yourself when dealing with mains AC =).
HERE is the project that got me started some time ago.
It uses AVRs so it should be easy to adapt to an arduino.
It is also quite complete, with schematics.
Their software is a bit on the complex side, so you should start with something simpler.
There is just a ton of this kind of stuff at the Make magazine site. I think you can even find some examples of similar hacks.
I use MOSFET for dimming 12V LED strips using Arduino. I chose IRF3710 for my project with a heat sink to be sure, and it works fine. I tested with 12V halogen lamp, it worked too.
I connect PWM output pin from Arduino directly to mosfet's gate pin, and use analogWrite in code to control brightness.
Regarding 2nd question about controlling lights, you can switch on/off 220V using relays, as partially seen on my photo, there are many boards for this, I chose this:
As a quick-start, you can get yourself one of those dimmerpacks (50-80€ for four lamps).
then build the electronics for the arduino to send DMX controls:
Arduino DMX shield
You'll get yourself both the arduino-expirience + a good chance of not frying your surrounding with higher voltage..