Mega 4 SPI channels

I am reading from a camera buffer and transmitting on a 2.4ghz transceiver, in addition to reading other sensors. I've read that the ATMega1280 has 4 serial transceivers.
Is it possible using either Arduino C or Armtel ASM to read from the camera buffer and transmit at the same time?
I do realize that no matter what I'm using multiple instructions, but I'm looking for a tighter pipeline than:
Enable Camera
Read Byte
Disable Camera
Enable 2.4
Write Byte
Disable 2.4
Repeat

I'd rather see something to the effect of
Enable Camera
Enable 2.4

loop{
Read Byte Camera
Write Byte 2.4
}

I would just connect the camera directly to the transceiver and control the pins with an external ic but I need to use the transceiver for other data in both directions as well.

BTW, this is for an RC Car project

The answers to this will help me decide if there is an advantage to using a Mega over an Uno.

Thanks for any and all help.

Your title suggests you want SPI, your question is about serial, which do you actually need?

A Mega has 4 serial ports, yes. The first of those 4 ports is taken up by the serial monitor, so is not really available unless you really know what you are doing. The other 3 are free for you to use as you please.

There is no problem reading and writing from / to all the serial ports concurrently, serial is a LOT slower than the processor, it will be able to keep up. The only thing is you must write cooperative, non-blocking code, which many people new to writing code struggle to get their heads around. Non blocking means no delay(), no while() and only very short and quick for loops, if any at all.

Here are some tutorials:

1 Like

How many frames, pictures, per second do You need to transfer? How many bytes per frame?

Thank you for your detailed answer.
I'm using an OV7670 640X480 camera module and an nRF24L01+ 2.4GHz transceiver because I have those on hand.
Data sheets:
Camera https://www.voti.nl/docs/OV7670.pdf
Transceiver https://www.sparkfun.com/datasheets/Components/nRF24L01_prelim_prod_spec_1_2.pdf

If I'm reading these correctly, big if, the camera is serial, single bidirectional data line and the transceiver is SLI. So, both Serial and SLI.

At the time of this rely I have not read your links, but I will directly. I just wanted to provide an initial reply first.

I teach 3rd and 4th level programming - Python, Java, C++, elementary - undergrad, so hardware control programming is a fringe topic in my professional life, but in on my own I've done a lot of reading but little practice. I expect to make well educated guesses and many mistakes too.
That being said, I plan on approaching the coding efficiency problem using a switch in my main loop and a time slice index.

Many widget operations poll a sensor, poll transceiver, change motor state, pulse servo, serial write will need to happen in sequence.
In a higher level language, I'd write a function for each and in my loop I'd use a if based decision tree based on a time index to see if that function needed to be called in that iteration. That would make for many reference calls and a lot of time wasted making decisions. I believe that I need to eliminate the functions and most of the decisions from that logic and opt for a perfectly rigid design.

Instead, I plan on mapping out on paper how often I need each operation to happen per second to achieve the proper operation of the overall machine. If I assign each operation a frequency count of 0-7 then I can create 8 time slices with different combinations of the necessary widget code.

In each slice will be a copy of the code for each widget operation in the order that it needs to happen. This means I will have multiple instances of the same code but no functions.
Edit: As I understand the C compiler, creating sequential cases starting at zero usually makes to compiler opt for a speedy single operation look-up table. This being the fastest possible code branching for more than two options.

I will then put the time slices into a switch that's evaluated each iteration of the main loop. The switch is based on a slice index. After the switch and slice code is evaluated I will increment the slice index.
Edit: I will need to consider a different method of changing the slice index as some slices will only run once in a cycle and others will run many times. I can probably work out a simple pattern.

Instead of using the modulus operator or an if statement I will mask the last three bits as the value for the switch, so the value self modulates and the time to do this is fixed and predictable.

Edit: I see this model as my interpretation of a real-time system that provides the exact same responses in the exact same amount of time regardless of the state of the machine.

I am considering also if it would be simpler/faster to use a Mega and make a code based solution for the transposition of data, of If I should use and Uno and a transceiver based switch so I can pipe selected serial data directly from the camera to the transceiver while using the MCU to operate the controls. Possibly freeing up a few steps and still using the cheaper machine.

This project is in its early stages, I just want to make sure I'm barking up the right tree before I begin the real work.

I am putting a little more info in my other reply on this thread.

When the camera is going to be transmitting data it will be in QCIF 176 × 144 resolution. The screen it's going to is a 130x130 so I will ignore the the top and bottom 23 rows and the first and last 7 pixels from each row.

In this mode each pixel is a single RGB byte 2:4:2.

Ideally I will be able to burst read and transmit one entre row at a time in my time slice. 130 bytes at a time over SLI to transmit, however fast I can read it from the camera.

Edit: Frame rate will be a product of how fast I can get the data from the camera to the transceiver, to the other transceiver to an Uno, and from the Uno to the screen. If I get 3-5 FPS I will consider the project a success, beyond that is gravy.

The data sheet for the camera says it has a SCCB data interface, which I am not familiar with. However, it lists a bidirectional data connection and a clock connection. Serial does not use a separate clock, so that rules out it being serial. SPI does use a clock but is not bidirectional, it uses separate pins for Tx and Rx, so it's not SPI either, so I can't help you with SCCB, maybe someone else knows or maybe it is something you'll have to research.

The nRF24L01 uses SPI, so again not serial. Lots of stuff on this web site about SPI, SPI is no problem with just about every micro-controller you can find.

In that case you might find the serial input basics useful, you probably don't need the millis() or several things at the same time tutorial UNLESS you are used to having an OS schedule everything for you. On micro-controllers, especially the smaller ones, you have to do that yourself.

You're over-thinking this, do the if / else tree or do the switch / case thing, don't worry about wasting time doing if / else. If you don't have the spare processor time for this then you need a more powerful processor. My code is typically a small number of high level functions that get called one after the other from loop(). Each function starts with something that decides if there is anything for the function to do (for example: if(some amount of time has elapsed) {do stuff}; otherwise return without doing anything). That's all you need, if later it becomes clear you need something more complex then build it, otherwise don't bother.

I've not done anything with video, or even still images, but have a look at how much data the camera generates for 1 frame, have a look at how much RAM an ATMega1280 has. I think you'll realise it's not up to the job.

1 Like

I've seen Megas and Unos do video + other stuff projects, so I can't dismiss the idea out of hand.
The camera's odd protocol bothers me so I've upgraded to the OV2640 based on the esp32. This unit also has WiFi which is an added bonus as I can write an android/ios/web app for it as well.

I am going to make the esp32 into the communications hub and slave it to the Mega. The esp32 will be linked by either WiFi or the 2.4 direct transceiver to the remote unit. Two interrupt pins will allow bidirectional interrupts.

On the remote unit the screen and transceiver will be controlled by the Uno and a switch will allow the data to be written directly from the transceiver to the screen buffer. The great speed of the esp32 will allow any image data processing before transmission to facilitate this. The switch is just a few transistors, fast and cheap.

In this scheme:
The Mega has no idea that the camera exists
The Uno knows of the camera but only handles routing the data
Dual modes of communication are available
The camera is mostly free to take pictures and limited video without affecting the responsiveness of the machine
I should have increased image bandwidth for higher resolution and/or greater framerate
Programming for the Mega and Uno are simplified considerably, and thus can be more flexible and agile

The bandwidth for the nRF24L01+ is 2Mbps or 250,000 Bytes per second.
I've opted for a 320x240 screen with the ILI9341 controller.
If I transmit the entire frame it takes 76,800 bytes.
I could transmit 3 per second and still have 9% of each second left to transmit commands.
However if I always convert to 320x240 in the esp32 first, I can then do 19,200 4 Byte comparisons by subtraction and a tolerance comparison (mask out the bottom to bits green of each Byte Ob11110011111100111111001111110011 for RGB 2:4:2 to RGB 2:2:2) and only transmit changed data in an MP4esque compression and only transmit changed Bytes in groups of 4.
I may try to always transmit 6 bit pixels too, but I'm not sure if I can handle the conversion on the other end yet.
Edit: On receiving 6 bit pixels:
If the receiving Uno can catch half of that data bandwidth and 4 pixels are transmitted per 3 Bytes, then the Uno can potentially receive about 160,000 pixels per second.
WAG (Wild Butt Guess) of 50% pixels needing to be changed per frame means I could achieve an effective 4 FPS
Either way I'm likely capped at 3 or 4 FPS which is still a success for this project.
I will test both models as this one may yield better results than expected, but I expect the added complexity is not likely to be worth it

I'm keeping the 2.4 direct transceiver because I do not want the unit to be WiFi dependent.

I appreciate the effort you put into your responses. They are very helpful.

Edit: 3 FPS is actually very good. Check out this video: 3 fps (Frames Per Second) Magic Lantern 2.3 EOS 60D - YouTube

Thank you.

I think I am at the limit of the help I can give you, your project is too different from anything I have done for me to offer much else. I hope someone else will pick up from here and offer more advice.

Good luck with your project.

You've done a lot to point me in the right direction and you are a productive member of this community.
I now have a primary plan and with a single fork and I'm good to make the attempt now.
I am very likely to need more help, but I will make new posts to ask specific questions rather than continuing this thread.
I will show off my results too, of course.

Off topic, but what kinds of projects do you like to work on?

I've had a life long project: When I was 19 or 20 I lay in bed listening to the central heating thermostat clicking on and off and thought "I can do better". Since then I have built numerous heating controllers with relays, with CMOS logic and with a variety of PIC micro-controllers. My current version has a Nextion HMI for displaying what's happening and for changing settings, and uses an ESP8266 board to get the time from an NTP server and to connect to various sensors.

Currently working on a new version of a light controller for room lights.

You will have seen my tutorials on this site, each of those was an interesting project.

When I come home in the evening and press the remote control for the garage door all the outside lights come on.

Very Cool!

I ran a construction company for many years around the turn of the century. Efficiency of HVAC and Power were always a big ticket item in my designs.
I used a Panasonic Toughbook tablet as the heart and ran my own OS on it, based on multithreading DR DOS. I mounted it in the kitchen. It connected to an ethernet network that ran on low bandwidth mode that used the house's power lines for harmonic transmissions. Now WiFi would make that much cheaper. Temperature sensors were in every room along with electronically controlled dampers on each register and a variable speed blower motor. Each room's temp was individually controllable +/- 5 degrees from the rest of the house on average. It also turned off the water heater at night and allowed for fairly complex power saving planned controls.

I will look into your designs. I'm very interested.

I haven't gotten around to automating my outdoor lights, but I will be thinking about it now.

1 Like

My dad did the opposite: ground works and demolition. He had a licence for demolition explosives; it was quite normal for there to be a box of dynamite in the house when I was growing up!

1 Like

The opportunity to make a Dad joke about dynamite is one I just can't re-fuse.

1 Like

In theory, the USART ports are capable of doing SPI in "master mode", so you could have up to 5 SPI ports operating "simultaneously."
In practice, the Arduino Mega boards do NOT break out the pins needed to make this work (especially: what would be the clock pins.) But if you were to use one of the other ATmega2560 boards, that might help.

A bunch of the SAMD boards can probably run multiple SPI ports as well (I haven't check the pinouts.)

1 Like

Good info, thank you.

Do you have an example or two of a cheap ATmega2560 board that can properly achieve master mode, please?

Cheap? No :frowning:
Maybe OLIMEXINO-2560 - Open Source Hardware Board

Note that it would also require a pretty substantial software effort to implement SPI on the USARTs - that's not currently available in the Arduino core. Thus more of the "In theory" disclaimer...

Blockquote @westfw Note that it would also require a pretty substantial software effort to implement SPI on the USARTs - that's not currently available in the Arduino core. Thus more of the "In theory" disclaimer...

Wow, that board is expensive.

I get new old stock 104MHz CPLDs for under a dollar. I can make a switching network more easily than I can write a driver for such a complex operation, and my driver experience is limited to bit banging so it might not be super efficient. The CPLD needs no driver, just a couple command pins using port manipulation: Arduino - PortManipulation.

In this case I'm going to offload the serial tasks to a better processor on one end and directly to the buffer on the other.

You do realize that the mega2560 is about $12 for just the chip?
A $15 board is pretty crazy cheap, IMO. Most of the 2560 boards in a in the $40 range.0

(yes, there are fewer "clone" megas with counterfeit chips.)

This is another reason (besides performance) to start looking at ARM cores instead of AVRs. A RPi Pico has two accessible HW SPI ports with DMA, plus (probably) the ability to do more with their neat "PIO" hardware, and costs as little as $4. Some of the STM32F103 boards should be in that range as well.

Yes, for me it's expensive to get it shipped, more than the board.
I usually get my boards in bulk from China. <$3 for an Uno <$10 for a Mega.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.