What happens with errors on Arduino during runtime? - runtime

If using Arduino, what would it do if I used code like this:
int status;
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, status);
}
What would thiscode do? Would the LED turn on? Would it damage the chip? When compiling in the Arduino IDE, it said it was fine. There are other issues that the compiler won't catch, but what will they do? One other example is doing "digitalRead();" while it is set as an output.
Note: Using Arduino Uno SMD edition R2.

You will not damage the Arduino, but you cannot be sure about the output, since the value is not initialized. It holds whatever value the memory holds in its location (think of it as an unknown random value). Most probably though, it will be turned on, because digitalWrite sets the pin to high if you pass anything other than LOW (=0) to it. Look at Arduino's source code in wiring_digital.c:
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
Regarding your other questions:
Reading a pin value returns PINx register value, which is the physical state (high or low) of the pin, regardless of its mode (in or out).
In general, it is really difficult to damage Arduino, and in most cases you need to apply some high/negative voltage on some pins to damage it.

Related

ESP32 failing to detect PN532 NFC module

I've been struggling for the past few days to get the Elechouse PN532 V3 module working with an ESP32 over I2C. The PN532 module itself works fine with a Raspberry Pi.
This is the circuit (not actually using SparkFun ESP32 board, just for reference)
And this is the code I'm trying to run
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);
void setup(void) {
Serial.begin(115200);
Serial.println("Hello!");
Wire.begin(18, 19);
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata) {
Serial.print("Didn't find PN53x board");
while (1); // halt
}
// Got ok data, print it out!
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
nfc.setPassiveActivationRetries(0xFF);
// configure board to read RFID tags
nfc.SAMConfig();
Serial.println("Waiting for an ISO14443A card");
}
void loop(void) {
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
// Wait for an ISO14443A type cards (Mifare, etc.). When one is found
// 'uid' will be populated with the UID, and uidLength will indicate
// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
if (success) {
Serial.println("Found a card!");
Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print("UID Value: ");
for (uint8_t i=0; i < uidLength; i++)
{
Serial.print(" 0x");Serial.print(uid[i], HEX);
}
Serial.println("");
// Wait 1 second before continuing
delay(1000);
}
else
{
// PN532 probably timed out waiting for a card
Serial.println("Timed out waiting for a card");
}
}
And finally the serial output: Didn't find PN53X board
Any ideas what I'm doing wrong?
EDIT: libraries im using https://github.com/elechouse/PN532 and the ESP32 dev board is a Wemos Lolin32 Lite clone.
I don't have any of this hardware to verify this, but from 'PN532-PN532_HSU\NDEF\README.md'
For the Adafruit Shield using I2C
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
Try using the above in your code? I'd also suggest you review the PN532 I2C examples in more depth. The PN532 I2C library code defines a 'wakeup' function:
void PN532_I2C::wakeup()
{
delay(500); // wait for all ready to manipulate pn532
}
The comment makes me believe the device may require a significant delay (500ms) before it's ready to talk.
Best of luck.
sda and scl are 21 and 22
also make sure that you changed mode to I2C (those jumpers on PN532 module):
doc - page 3
I have this now working with an M5STACK grey core, the common issue was the I2C bus would lock up on a reset or re program. Use a spare I/O pin and connect to the PN532 reset pin, hold this low on boot, initialize I2C bus then drive reset high after 100mS problem solved no more bus conflicts.

Control relay from PIC18 microchip

I have a PIC18F24K20 microchip, and wants to control a relay. It works fine from my RasPI over GPIO - but i cant get it working trough my microchip.
My test program is this:
#include <xc.h>
#define R1 LATBbits.LATB0
#define R1_TRIS TRISBbits.RB0
#define R2 LATBbits.LATB1
#define R2_TRIS TRISBbits.RB1
void main(void) {
R1_TRIS = 0;
R2_TRIS = 0;
R1 = 1;
R2 = 0;
return;
}
What is im doing wrong?
replace the return;
with:
while(1)
{
ClrWdt();
}
according datasheet,RB0 and RB1 have several modules connected to these pins,so you should verify they are turned off:
Analog,
ECCP,
Comparator.
BTW why using two pins in order to control one relay?
3.you may need add driver in order to operat the relay.
according datasheet, add following initialization code:
CCP1CON=0;
CCP2CON=0;
ADCON0=0;
CM1CON0=0;
CM2CON0=0;
also PBADEN bit at configuration bit should be zero.
The main function should never return in the embedded PIC processors. In some implementations, it would cause a software reset which would cause your pins to go back to high impedance mode. Try adding while (1); at the end of your main.
Check if the used pins have other functions. The typical gotcha is that the pins double as analog pins and are enable by default.
Disable them by looking up which AN pin they correspond to in the datasheet and disable them with code like
ANSEL.ANS0 = 0;
ANSEL.ANS1 = 0;
If you enable watchdog functionality you also might want to add a
ClrWdt();
to the main WHILE loop (which was a good suggestion from Mathieu)

How to send signal from kernel to user space

My kernel module code needs to send signal [def.] to a user land program, to transfer its execution to registered signal handler.
I know how to send signal between two user land processes, but I can not find any example online regarding the said task.
To be specific, my intended task might require an interface like below (once error != 1, code line int a=10 should not be executed):
void __init m_start(){
...
if(error){
send_signal_to_userland_process(SIGILL)
}
int a = 10;
...
}
module_init(m_start())
An example I used in the past to send signal to user space from hardware interrupt in kernel space. That was just as follows:
KERNEL SPACE
#include <asm/siginfo.h> //siginfo
#include <linux/rcupdate.h> //rcu_read_lock
#include <linux/sched.h> //find_task_by_pid_type
static int pid; // Stores application PID in user space
#define SIG_TEST 44
Some "includes" and definitions are needed. Basically, you need the PID of the application in user space.
struct siginfo info;
struct task_struct *t;
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = SIG_TEST;
// This is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space, and kernel space should use SI_KERNEL.
// But if SI_KERNEL is used the real_time data is not delivered to the user space signal handler function. */
info.si_code = SI_QUEUE;
// real time signals may have 32 bits of data.
info.si_int = 1234; // Any value you want to send
rcu_read_lock();
// find the task with that pid
t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
if (t != NULL) {
rcu_read_unlock();
if (send_sig_info(SIG_TEST, &info, t) < 0) // send signal
printk("send_sig_info error\n");
} else {
printk("pid_task error\n");
rcu_read_unlock();
//return -ENODEV;
}
The previous code prepare the signal structure and send it. Bear in mind that you need the application's PID. In my case the application from user space send its PID through ioctl driver procedure:
static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
ioctl_arg_t args;
switch (cmd) {
case IOCTL_SET_VARIABLES:
if (copy_from_user(&args, (ioctl_arg_t *)arg, sizeof(ioctl_arg_t))) return -EACCES;
pid = args.pid;
break;
USER SPACE
Define and implement the callback function:
#define SIG_TEST 44
void signalFunction(int n, siginfo_t *info, void *unused) {
printf("received value %d\n", info->si_int);
}
In main procedure:
int fd = open("/dev/YourModule", O_RDWR);
if (fd < 0) return -1;
args.pid = getpid();
ioctl(fd, IOCTL_SET_VARIABLES, &args); // send the our PID as argument
struct sigaction sig;
sig.sa_sigaction = signalFunction; // Callback function
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig, NULL);
I hope it helps, despite the fact the answer is a bit long, but it is easy to understand.
You can use, e.g., kill_pid(declared in <linux/sched.h>) for send signal to the specified process. To form parameters to it, see implementation of sys_kill (defined as SYSCALL_DEFINE2(kill) in kernel/signal.c).
Note, that it is almost useless to send signal from the kernel to the current process: kernel code should return before user-space program ever sees signal fired.
Your interface is violating the spirit of Linux. Don't do that..... A system call (in particular those related to your driver) should only fail with errno (see syscalls(2)...); consider eventfd(2) or netlink(7) for such asynchronous kernel <-> userland communications (and expect user code to be able to poll(2) them).
A kernel module could fail to be loaded. I'm not familiar with the details (never coded any kernel modules) but this hello2.c example suggests that the module init function can return a non zero error code on failure.
People are really expecting that signals (which is a difficult and painful concept) are behaving as documented in signal(7) and what you want to do does not fit in that picture. So a well behaved kernel module should never asynchronously send any signal to processes.
If your kernel module is not behaving nicely your users would be pissed off and won't use it.
If you want to fork your experimental kernel (e.g. for research purposes), don't expect it to be used a lot; only then could you realistically break signal behavior like you intend to do, and you could code things which don't fit into the kernel module picture (e.g. add a new syscall). See also kernelnewbies.

Pic16f877a lcd code not working

i have been recently learning microcontroller and now I am trying to make an LCD program with MPLAB X ide and XC8 but in the hard way using no libraries of XC8 but it is not working at all here are all the details:
Components:
LCD LM016L
Microcontroller pic16f877a
Pin connections:
Register select pin --> pin E0, Read/Write pin --> pin E1, Register Select pin --> pin E2
Data lines (8 bits mode) port D.
Now this is the whole code:
#include "config.h"
//port E pin 0 --> RS, pin 1 --> R/W, pin 2 --> En
#define RS TRISE0
#define RW TRISE1
#define EN TRISE2
void blinkEnable(void);
void check_if_busy(void);
void send_a_command(int command);
void send_a_character(int character);
void main(){
blinkEnable();
__delay_ms(10);
check_if_busy();
__delay_ms(10);
send_a_command(0x01);
__delay_ms(10);
send_a_character(0x46);
while(1){
}
}
void blinkEnable(){
TRISEbits.EN = 1;
__delay_ms(10);
TRISEbits.EN = 0;
__delay_ms(10);
}
void check_if_busy(){
TRISEbits.RS = 0;
TRISEbits.RW = 1;
TRISDbits.TRISD7 = 1;
while(PORTDbits.RD7 == 1){
}
}
void send_a_command(int command){
TRISEbits.RW = 0;
TRISEbits.RS = 0;
PORTD = command;
}
void send_a_character(int character){
TRISEbits.RW = 0;
TRISEbits.RS = 1;
PORTD = character;
}
If you are beginner to microchip microcontroller, I recommend you to try flowcode software developed by Matrix Multimedia which provides graphical programming environment where you just have to place blocks to access modules (say LCD module in your case) instead of writing code (flowcode will write code for you and you just have to give inputs and get output ). Best part is , you can see c code for every block you have used which gives a clear idea for beginners what program should me written to access different modules and another best part is, you can simulate entire code on the flowcode software before running on the hardware and flowcode has got one of the best compiler for microchip microcontrollers..
You can use the XC8 library by electroSome. You can download the library header file from their website and include it in your project. It is very easy.
Use this link :
Interfacing LCD with with PIC Microcontroller - MPLAB XC8
Though it is a good practice of making your own functions, but I suggest you to use already compiled and tested libraries to save your time and effort, also you can use MikroC compiler that already has bunch of software libraries available, and it is much easier to understand.

USART problems with ATmega16

I have a ATMega16 and have looped the Rx Tx (just connected the Rx to the Tx), to send and receive one char in a loop. But i only seems to be receiving 0x00 instead of the char i send.
I have the CPU configured to 1MHz.
But my thought is that since the Rx and Tx are just looped, it shouldn't matter what speed i set, since both are the same?
So basically, I'm trying to get a LED to flash at PORTC when receiving the correct char.
Here is the code:
#ifndef F_CPU
#define F_CPU 10000000
#endif
#define BAUD 9600
#define BAUDRATE ((F_CPU)/(BAUD*16)-1)
#include <avr/io.h>
#include <util/delay.h>
void uart_init(void){
UBRRH = (BAUDRATE>>8);
UBRRL = BAUDRATE;
UCSRB = (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1);
}
void uart_transmit (unsigned char data){
while (!(UCSRA & (1<<UDRE)));
UDR = data;
}
unsigned char uart_recive(void){
while(!(UCSRA) & (1<<RXC));
return UDR;
}
int main(void)
{
uart_init();
unsigned char c;
PORTC = 0xff;
DDRC = 0xff;
while(1)
{
_delay_ms(200);
uart_transmit(0x2B);
c = uart_recive();
if(c==0x2B){
PORTC = PORTC ^ 0xff;
}
}
}
Any thoughts of what i am doing wrong?
The code seems right.
Thing you may have to check:
if your baudrate is the one you should have
if you try to send a char like 'p'; now you are sending a '+'
check your port configuration and see if it matches to your configuration
I think the last one is the problem.
You can try this code from ATMega manual:
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
After building your program, go to your port configuration and make sure it it set on 8 bits data format and 2 stop bits. Then test it on you microcontroller and see what happens. Please come back with the result.
Consider real baudrate accuracy. See e.g. http://www.wormfood.net/avrbaudcalc.php?postbitrate=9600&postclock=1, AVR provides 7.5% error for 9600baud # 1MHz clock, which is rather high error. Depend what you are sending and receiving. "Normally" you can see a garbage, if you receive permanently 0x00s it looks like another problem.
your F_CPU is set to 10MHz.
you sad that it is configured to 1Mhz.
Also check your Fuses if you really activated the crystal.
If you just use the internal oscillator: it has a relatively large error so that your UART timings may be broken (i never got problems using internal oscillator for debugging).
Another source of error may be your F_CPU definition. Mostly this Preprocessor constant is defined already (propably also wrong) in Makefile (or in IDE project settings) so your #define in Code has not affect since the #ifndef
PORTC pins(TDI,TMS,TCK,SDA) always high because these pins for JTAG and JTAG is enable by default. if you want to use PORTC in your application you have to Disable the JTAG by setting fuse bit. for atmega16 JTAGEN is fuse bit set it to 1(means unprogrammed). in case of fuse bit 0(means programmed) and 1(means unprogrammed) one more thing if you use more than 8MHz you have to set fuse bit otherwise your program will give unexpected or wrong result thanks.

Resources