If the input pin is not pulled LOW or HIGH, the value will float. That is, it won't be clearly a 1 or a 0, but somewhere in between. For digital input, a pullup or pulldown resistor is a necessity.
The Arduino Mega has four serial ports which there can be choosed from. They are accesed in the following way
Serial.begin(9600);
Serial1.begin(38400);
Serial2.begin(19200);
Serial3.begin(4800);
The serial port on an Arduino can be set with additional parameters. The config parameter sets data bits, parity, and stop bits. For example:
8 data bits, even parity and 1 stop bit would be - SERIAL_8E1
6 data bits, odd parity and 2 stop bit would be - SERIAL_6O2
7 data bits, no parity and 1 stop bit would be - SERIAL_7N1
If randomSeed()
is called with a fixed value (eg. randomSeed(5)
), the sequence of random numbers generated by the sketch will repeat each time it is run. In most cases, a random seed is preferred, which can be obtained by reading an unconnected analog pin.
Other than in ordinary C / C++ , the Arduino IDE allows to call a function before it is defined.
In .cpp files, you have to define the function, or at least declare the function prototype before you can use it.
In an .ino file, the Arduino IDE creates such a prototype behind the scenes.
Serial.println(val)
For help with Serial communication, see: Serial Communication
Common Mistake : If you keep the rx and tx pins at default values (0 and 1), you cannot upload new code until and unless you remove it, so it's almost always better to change the tx and rx pins in the SoftwareSerial constructor.
For the Arduino Pro Mini, use the mini squid cable as shown, again connecting the other side the debugger's AVR port.
For debugging with the Uno, you will need to cut the Reset-enable trace (you can always solder it back for using with the Arduino IDE):
Using the Pro Mini, if you intend to connect the serial port to your computer using an FTDI board, do not connect the DTR line, as it will interfere with Atmel's Serial Wire Debug (SWD) interface. I simply connect power, ground, Tx and Rx as shown here below. Rx and Tx on Arduino go to Tx and Rx, respectively on FTDI board. Some FTDI boards are labeled differently, so if the serial port doesn't work, swap Rx and Tx.
You will have to provide power separately to the Arduino because the debugger will not power it. This can be done on the Pro Mini through the FTDI board as shown above, or with a USB cable or AC adaptor on the Uno.
Plug the Atmel ICE into your computer, start Atmel Studio and you can now import an existing Arduino project.
In Atmel Studio, go to File -> New -> Project and select "Create project from Arduino sketch". Fill out options including board and device dropdown menus.
Go to Project -> yourProjectName Properties, click on Tool, select Atmel ICE under debugger/programmer and debugWire under interface. Go to Debug -> Start debugging and break. You should see a warning and be asked if you want to set the DWEN fuse. Choose OK, unplug the Arduino from power and plug it in again. You can stop debugging by clicking the red square button and start by clicking the green triangle button. To return the Arduino to a state that it can be used in the Arduino IDE, while you're debugging, choose Debug -> disable debugWIRE and close.
Note that any functions you add must include a function prototype as well (loop and setup don't need them). You can see the ones Atmel Studio added at the top of the sketch if there were any functions when you imported your project into Atmel Studio (see sample code for example).
C++11 support is enabled by default in Arduino 1.6.6 and above. This provides more C++ language features and enabling it may increase compatibility with the Arduinio system. To enable C++11 in Atmel Studio 7, right click on your project file, select properties, click on ToolChain on the left, Click on Miscellaneous under AVR/GNU C++ Compiler and put -std=c++11
in the Other flags field.
Copy the .cpp library file into C:\Users\YourUserName\Documents\Atmel Studio\7.0\YourSolutionName\YourProjectName\ArduinoCore\src\core
, then in Atmel Studio, open the Solution Explorer window right click on the Arduino Core/src/core folder, choose add -> existing item and choose the file you added. Do the same with the .h library file and the YourProjectName/Dependancies folder.
You can always have the Android IDE open and use that Serial window (just select the correct serial port), however to add a built in Serial window to Atmel Studio, go to Tools -> Extensions and Updates, click on Available downloads and search for Terminal Window or Terminal for Atmel Studio and install it. Once installed, go to View -> Terminal Window.
Programming Arduino with a moder IDE like Atmel Studio 7 gives you numerous advantages over the Arduino IDE, including debugging, autocompletion, jump to definition and declaration, forward/backward navigation, bookmarks and refactoring options to name a few.
You can configure key bindings by going to Tools -> Options -> Environment -> Keyboard. Some that really speed up development are:
General Remark
If you intend to create a loop to wait for something to happen, you're probably on the wrong track here. Rather remember that all code after setup() is run from a method called loop(). So if you need to wait for something, it's easiest to not do anything (or only other independent stuff) and come back to check for the waiting condition next time.
do { } while(condition)
will not evaluate the condition statement until after the first iteration. This is important to keep in mind if the condition statement has side effects.
Interrupt Service Routines (ISRs) should be as short as possible, since they pause main program execution and can thus screw up time-dependent code. Generally this means in the ISR you set a flag and exit, and in the main program loop you check the flag and do whatever that flag is supposed to do.
You cannot use delay()
or millis()
in an ISR because those methods themselves rely on interrupts.
For very simple sketches, writing blocking code using delay()
and delayMicroseconds()
can be appropriate. When things get more complex, using these functions can have some drawbacks. Some of these are:
delay()
is called in subroutines that are not obviously called, for example in libraries you include.delay(500)
.millis()
usually relies on a hardware timer that runs at a speed that's much higher than 1 kHz. When millis()
is called, the implementation returns some value, but you don't know how old that actually is. It's possible that the "current" millisecond just started, or that it will end right after that function call. That means that, when calculating the difference between two results from millis()
, you can be off by anything between almost zero and almost one millisecond. Use micros()
if higher precision is needed.
Looking into the source code of elapsedMillis
reveals that it indeed uses millis()
internally to compare two points in time, so it suffers from this effect as well. Again, there's the alternative elapsedMicros
for higher precision, from the same library.
Most slaves have an active low chip select input. So proper code to initialize and use a chip select pin is this:
#define CSPIN 1 // or whatever else your CS pin is
// init:
pinMode(CSPIN, OUTPUT);
digitalWrite(CSPIN, 1); // deselect
// use:
digitalWrite(CSPIN, 0); // select
... perform data transfer ...
digitalWrite(CSPIN, 1); // deselect
Deselecting a slave is just as important as selecting it, because a slave may drive the MISO line while it is selected. There may be many slaves, but only one may drive MISO. If a slave is not deselected properly, two or more slaves might be driving MISO, which may lead to shorts between their outputs and might damage the devices.
Transactions serve two purposes:
The clock line has different idle states in the different SPI modes. Changing the SPI mode while a slave is selected might confuse the slave, so always set the SPI mode before selecting a slave. The SPI mode can be set with an SPISettings
object passed to SPI.beginTransaction
:
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(CSPIN, 0);
... perform data transfer ...
digitalWrite(CSPIN, 1);
SPI.endTransaction();
SPISettings
may also be stored elsewhere:
SPISettings mySettings(1000000, MSBFIRST, SPI_MODE0);
SPI.beginTransaction(mySettings);
If another part of the code tries to use the SPI between a pair of calls to beginTransaction()
and endTransaction()
, an error may be raised - how that is done depends on the implementation.
Also see Arduino Reference: SPISettings
If the SPI has to be used within an ISR, no other transaction may be taking place at the same time. The SPI library provides usingInterrupt(interrupt_number)
to facilitate this. It works by disabling the given interrupt whenever beginTransaction()
is called, so the interrupt cannot fire between that pair fo calls to beginTransaction()
and endTransaction()
.
The allowable addresses vary by hardware.
I use an Arduino Uno with Arduino IDE 1.6.9 and Python 2.7.12 running in Windows 10.