I'm working through a set of beginner exercises with the Arduino Uno microcontroller. (A generic one, though, as this is what I've been supplied with.)
The program I'm running, which alternates between sending 1's and 0's to serial output depending on the state of a momentary switch, has set pin 2 to be the input for the switch. But. Whilst wiring up, I accidentally plugged the jumper cable in to pin 3 initially, and found it still mostly sent the 1's when the button was pushed. Some 0's, yet mostly 1's.
Initially I thought maybe it was just the board was a bit dodgy, but thought I'd experiment a bit. Plugging into pin 3 instead of pin 2 still fairly consistently sent 1's when the button was pushed, though the 1's flowed a little bit less consistently than when it was in pin 2. In pin 2 it was completely consistent by comparison. So I tried pin 4, but with that one there's no response at all.
Am I right in presuming the program's readings seems to get a little bit less responsive the further away I move the cable from the pin that I've programmed to act as input? Can anyone help me understand why this happens?
It's probably quite obvious that I'm new to electronics. :)
The program I've got uploaded to the board is as follows:
// digital pin 2 has a pushbutton attached to it. Give it a name:
int pushButton = 2;
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// make the pushbutton's pin an input:
pinMode(pushButton, INPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input pin:
int buttonState = digitalRead(pushButton);
// print out the state of the button:
Serial.println(buttonState);
delay(1); // delay in between reads for stability
}
Floating pins are prone to noise. If you are not actually connecting anything to pin 2, you will be reading noise. Any wire connected to pin 2 (even connections on the board) will act like an antenna and pick up noise. You should always use the pin number that you are physically connecting in situations like these.
Leaving input pins open makes the microcontroller read a floating value which swings between 0 to 1. Also when wiring a switch to any pin, make sure to hook some pull-down resistor to make the input 0.
These are common for many electronics and proper notice to be taken while designing circuits of your own.
You need to look into datasheet where described functions of the pins.
The pins of MCU can be assigned various functions through special registers.
Two most common functions of the pins are input and output. MCUs provide internal pull-up and pull-down resistors which when used properly significantly simplifies electronic schemas.
If the input activated as input without any pull-??? then it's state is not defined and can be used as initiator of random number generator. Due this reason it is better to define what is default state of the input pin by connecting pull-??? resistors.
In Arduino IDE you are not limited to functions provided -- you still can use register manipulation directly, you just need to learn internals of the MCU.
If you do it properly then 2kbit program very often can be made as small as a few hundred bytes and it will work hundred times faster.
Operating registers in C is not much different from assembly, in C++ you get right away significant overhead -- although some benefits of registers still can be significant.
Libraries hide from programmers internals of MCU what is nice as it simplifies the programming and does not require to understand how MCU works, what registers are changed in what sequence.
But when you know hardware in and out -- you can squeeze from small MCU what is not possible with use of libraries (code will just not fit into the chip). MCUs are not that complicated (Atmel) to learn about it's internals -- benefits are significant.
Knowledge is a power which many avoid.
Related
I had written a code on atmel studio for blinking a led on pin 13. After uploading the code with xloader mega's builtin led was blinking.
I uploaded fade code on my mega and the builtin led was blinking instead of led. What should i do?
I am using arduino mega 2560.
int main(void)
{
DDRB=0b00000000;
while (1)
{
PORTB=0b10000000;
_delay_ms(1000);
PORTB=0b00000000;
}
}
What you should do? Read the manual.
Please refer to https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf
Chapter 13.2.
The DDxn bit in the DDRx Register selects the direction of this pin.
If DDxn is written logic one, Pxn is configured as an output pin. If
DDxn is written logic zero, Pxn is configured as an input pin.
Working with registers doesn't make sense if you don't know what they do.
DDRB=0b00000000;
Gives you inputs only.
why would you use Arduino and try to program it without its conventional macros and functions?
If you are trying to blink an led or make it breath then use the Arduino IDE and its built-in functions analogWrite() to generate a pwm pulse for your led or any led on suitable pins which support analogwrite(). You shouldn't try to do any direct modifications on registers if you have no suitable knowledge, because your risk destroying your development kit and maybe burning some other stuff around. Please use your kit's schematics to spot the pins which support analogwrite() and then use the code in examples.
That way you will achieve your goal faster and without any issues.
TL/DR: you have to set 7th bit in DDRB to one.
In AVR ports are configured by bits in two registers: DDRx and PORTx.
When the corresponding bit in the DDRx register is set to one, the port is configured as output. And the corresponding bit in the PORTx register chooses which electrical level is output on the pin. If it is 0 then internal MOSFET shorts the pin to "ground" lane, and sinks current from external source. When the bit of the PORTx is one, then the pin is connected to "VCC", sourcing big amount of current enough to lit up a LED.
But if the pin is connected to something, what consumes too much of current, or the pin is shorted to GND or VCC (let's say you have a button connected and pressed), then output MOSFETS might be overloaded and damaged.
If the bit in DDRx is set to zero, then the pin is configured as input. If the corresponding bit in the PORTx is zero, then the pin has no internal connection to power lines, it is called "Hi-impedance" state, or Tri-state. It does not source or sink any current. So, if no external source of current is connected, then pin level is floating, influenced by electrical interference. Logical level is not detectable and can change occasionally. If you want to connect, for example, a button (between the pin and GND), then logical level will be defined only when button is pressed. When it is released, the logical level will be undefined.
But! If the bit in the PORTx is set to one, then internal MOSFET connects the pin thru a resistor (about 35 kOhm) to VCC line. This make the pin to source a little amount of current, setting its logical level to high. Therefore, if a button is connected, when it is released, then pin will have defined high level. This is called "pull-up resistor". When button is pressed, it will not short and damage the MCU, because current flowing thru the button is limited by the resistor, but the logical level will be defined low.
What if instead of button you have a LED connected to the pin? Very small amount of current will flow thru the LED, makes it barely glow.
Read more in the datasheet (chapter 13. I/O-Ports)
This is driving me nuts for a couple of days now, so maybe you guys can give me some insights into what is going wrong.
I'm trying to read some data from an EEPROM (24LC16B) with an STM32(F0), but it just doesn't let me. I've tried an Arduino, which worked and does still work, so I do know that the wiring is correct.
This is my function to read the EEPROM data. (It is cut down to the very basis, just for testing): (Pastebin of my I2C_setup function)
uint16_t readEEPROMData(uint16_t deviceAddress, int memAddress){
// Wait while I2C peripheral is not ready
I2C_WaitForFlag(I2C_ISR_BUSY);
// Start I2C write transfer for 2 bytes, do not end transfer (SoftEnd_Mode)
I2C_TransferHandling(I2C1, 0xA2, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_WaitForFlag(I2C_ISR_TXIS);
// For testing purpose, be sure to generate a stop command...
I2C_TransferHandling(I2C1, 0xA2, 0, I2C_AutoEnd_Mode, I2C_Generate_Stop);
return I2C_COMM_STATUS;
}
Here's an pastebin of the Arduino library I used.
I've used a logic analyzer to see how the communication is going, and now I really don't understand it. Here's a printscreen of the working Arduino version:
And here's a printscreen of the STM32 communication:
Logic analyzer exports (viewable with Saleae Logic)
As you can see, I'm using the same address (although I had to use 0xA2 with the STM32), and there are no weird things happening, besides the NACK. So what could possible be wrong?
Confirm if all bus timing requirement are satisfied.
Confirm if their is adequate delay after every write cycle (5 mS)
Confirm is bus capacitance falls under permissible limit of I2C (400 pF - Theoretically).
Confirm if the correct VCC is supplied
As mentioned by you are interfacing EEPROM with MCU using cable you need to conform on capacitance.
You can use an oscilloscope to check if their are any distortion in waveform. You can use a LCR meter to check the capacitance.
Try reducing bus speed 25kHz to 50 kHz and check waveform.
Try increasing the strength of pull resister.
The problem with the wrong VCC capacity (4.2v instead of 5v for example) is, that the timing can be different to. (not fully verified, but it fixed the problem)
I am doing a class project involving an Arduino Uno and a Picaxe 14m2.
I am in the middle of attempting to code a program for the Arduino Uno that will allow me to send and output value to the input on the Picaxe.
So in layman's, this is what I wish to achieve:
I want the Arduino to check a sensor, and if the sensor returns a specific value. (- I know this part, but not the next.) I then want the Arduino to send a value (HIGH, or 1 .. something like that) as an output to one of the Picaxe input pins. I then need the Picaxe to notice a value has been sent, and then do something else.
Any help would be appreciated.
Thanks.
If you are looking for that, you may want to specify what kind of PICAXE you have.
Since there is a difference in the types of these chips.
After that you may wanna look over the datasheet of the PICAXE so that you can find the instructions set and the type of program memory you have, "EEPROM....".
After that:
List your Is/Os, inputs and outputs.
Set your source code editor.
Write the source code and burn it to the PICAXE program
memory.(C, Assembly...)
Write your Arduino code, setting the Is/Os and telling the
Arduino how to deal with the signals in and out.(C language)
Make a circuit diagram for the hardware you are going to connect
between both chips.
Don't forget to see the loading effects on both the Arduino and
the PICAXE, because you don't want to burn your project hardware
after all.
Test your project and note that you will have to troubleshoot
both software and hardware whenever a problem occurs.
I suggest that you use the Oscilloscope to test the signals going in or coming out of both circuits + the sensor's signal.
For any extra thing you need the PICAXE to do, use If statements, because they are not so technical to implement and they are easy to write and troubleshoot.
For your scheme, you are actually making the Arduino give instructions to the PICAXE through a variable signal coming from a sensor.
^send me feedback and I will help more.
You will probably want to look into using UART (aka Serial) or i2c communication.
Serial communication should work with any PICAXE and Arduino, While i2c Will only work if you are using the X2 Series PICAXE Chips. i2c's main advantage is when using multiple slave devices (plus the master device, i.e. more than just 2 devices total) in which you can use the same two wires for up to around 128 devices. Serial (UART) communication is simpler, and only needs one wire (plus a common ground) to send data one way, it is what i'll show for the rest of this answer
Here is the manual entry for serial input for the PICAXE, and Here's the entry for serial output from the Arduino. The code you will need given your question will be something like the following:
For the arduino:
void setup(){
Serial.begin(9600);
}
void loop(){
if (conditionMet){ //whatever the condition is in your code
int bytesSent = Serial.write(“HIGH”); //send the string “HIGH"
}
}
and for the PICAXE:
main:
serin 6, T9600, ("HIGH") 'uses qualifier to look for exact message "HIGH"
'do whatever when criteria met
goto main
I have an Arduino Mega connected to a 6 axis robotic arm. All 6 interrupts are attached to encoders (one encoder pin on an interrupt, the other on a vanilla digital input). The interrupts are handled with this code:
void readEncoder1(){
//encoders is a 2d array, where the first d is the axis, and the two pin numbers
//first pin is on an interrupt (CHANGE), and second is a standard digital in
if (digitalRead(encoders[0][0]) == digitalRead(encoders[0][1])) {
positions[0]++;
} else {
positions[0]--;
}
if(servoEnable){
updatePositions(); //// compares positions[] to targets[] and adjusts motor speed accordingly
}
}
This is designed to keep the arm locked at a certain position- if the arduino detects that the position of the motor is off by a certain threshold, it updates the power going to the motor to keep the arm in position.
The problem is this, then -- if two or three (or more) axis are under load (requiring constant updating to stay in position) or they are moving, the Arduino will stop receiving intact commands on Serial input, several characters will be dropped. The interrupts are obviously running quite quickly, and for some reason this is causing commands to become corrupted. Is there any way around this? Architecturally, am I doing this right? My main instinct is to call updatePositions() in the main run loop at, say, 100 ms intervals, will this significantly reduce interrupt overhead? I guess what my question boils down to is how do I get reliable serial commands into the Arduino even if all 6 encoders are pulsing away?
Quadrature encoders were designed to be read by hardware counters. Pulse rates are generally high with the motor running at full speed. One megahertz is not unusual. The higher the number of pulses, the better the servo loop works and the more accurate you can position the motor.
Doing this is in software with a low-power cpu is, well, challenging. It will fall apart when the ISR takes longer than the interval between pulses. You'll lose pulses and thus position. Especially bad because there is no way you can detect this error condition. And that this loss happens when the robot is moving fast, the worst case condition to lose control.
You absolutely cannot afford to update the servo loop in the interrupt handler so get rid of that first. Keep the ISR to the bare minimum, only count the position and nothing else. The servo loop should be separate, driven by a timer interrupt or tick. You cannot properly control a robot with a 100 msec servo update unless it is big an sluggish, this needs to be a handful of milliseconds at most to get smooth acceleration and stable feedback.
There's a limited amount of wisdom in spending forty bucks to control thousands of dollars worth of robot hardware. Not being able to keep up in the servo loop is something you can detect, shut it down when the position error builds up too much. There's nothing you can do about losing pulses, that's a wreck. Get the hardware counters.
First rule of embedded systems:
Do as little as possible in interrupts.
In your case, just update the positions in the interrupt and run your position/speed control loop in the background or at a lower priority.
Aside: I assume you are aware that you are "losing" encoder pulses as you don't have an interrupt on one of the channels?
Also, interrupt-driven encoder-analysis is very noise-prone. If you get a noise pulse, you'll likely only see an interrupt for one of the edges as they'll be too close together to process both.
A more robust way is to use a state machine which watches all 4 transitions, but that requires either interrupts on both edges of both channels, or polling fast enough to not miss anything up the to rate you are expecting to see.
I'm new to microcontroller programming and I have interfaced my microcontroller board to another device that provides a status based on the command send to it but, this status is provided on the same I/O pin that is used to provide data. So basically, I have an 8-bit data line that is used as an output from the microcontroller, but for certain commands I get a status back on one of the data lines if I choose to read it. So I would be required to change the direction of this one line to read the status thus converting this line as an ouput to an input and then back to an output. Is this acceptable programming or will this changing of the I/O pin this frequently cause instability?
Thanks.
There should not be any problem with changing the direction of the I/O line to read the status returned by the peripheral provided that you change the state of the line to an input before the peripheral starts to drive the line and then do not try to drive the line as an output until the peripheral stops driving it. What you must try to avoid is contention between the two driver devices, i.e. having the two ends being driven to opposite states by the processor and peripheral. This would result in, at best a large spike in the power consumption or worse blown pin driver circuitry in the processor, peripheral or both.
You do not say what the processor or peripheral are so I cannot tell whether there are any control bits in the interface that enable the remote device to output the status so that you can know whether the peripheral is driving the line at any time.
I've done this on digital I/O pins without any problems but I'm very far from an expert on this. It probably depends entirely on which microcontroller you are using though.
Yes, it's perfectly fine to change I/O direction on microcontroller repeatedly.
That's the standard method of communicating over open-collector buses such as I2C and the iButton. (see PICList: busses for links to assembly-language code examples).
transmit 0 bit: set output LATx bit to 0, and then set TRISx bit to OUTPUT.
transmit 1 bit: keep output LATx bit at 0, and set TRIS bit to INPUT (let external resistor pull-up line to high)
listen for response from peripheral: keep output LATx bit at 0, and set TRIS bit to INPUT. Let external resistor pull-up line to high when peripheral is transmitting a 1, or let the peripheral pull the line low when peripheral is transmitting a 0. Read the bit from the PORTx pin.
If both ends of the bus correctly follow this protocol (in particular, if neither end actively drives the line to high), then you never have to worry about contention or current spikes.
It`s important to remember that any IO switching in high speed generates EMI.
Depending of switching frequency, board layout and devices sensibilities, this EMI can affect performance and reliability of your application.
If you are having problems in your application use an oscilloscope to check for irradiated EMI in your board lanes.