|
I have a Duemilanove/168 and seem to be having an issue with an interplay between the serial port and Timer0. I'm trying to set up a watchdog timer that counts down over the course of ~1 second, disables the unit via setting a boolean to false if the watchdog gets to zero, or keeps the unit enabled by resetting the watchdog counter if a 'heartbeat' command is detected. The idea is that the control PC will send heartbeat commands periodically to keep the unit enabled during normal operation, but if communication is lost for any reason the Arduino-controlled system should shut itself down. The problem I'm seeing is that whenever I open or close the serial port from the control computer the watchdog timer gets reset even when no heartbeat command (or data of any other kind) is sent. This is mysterious since calling HeartBeatCommand() should be the only way to reset the watchdog, and as far as I can tell (by making that command turn on the on-board LED) it's never getting called. It's as if just opening/closing the serial port resets heartbeatWatchdogCounter to 0xFF, and the output pin (pin2) goes high for ~1 second. Any ideas as to what could be going on? My only guess is that something in the Arduino's serial com system is messing with my ISR for that timer, but that still wouldn't explain why the watchdog counter gets reset. semi-edit: While composing this post I decided that initializing heartbeatWatchdogCounter to zero was better than initializing to 0xFF, and that one change seems to have fixed the spurious resets caused by opening/closing the serial port on the control PC. I can't understand how that would matter, but it's some kind of clue at least. C++ code:
|
# ¿ Apr 21, 2013 15:37 |
|
|
# ¿ May 14, 2024 17:14 |
|
Fair enough. The simplified code below seems to reproduce the problem, opening or closing the Arduino IDE serial monitor window (ctrl+shift+M) opens the serial port and appears to reset the watchdog timer and makes pin2 high for ~1 second. It also appears to reproduce the issue where initializing heartbeatWatchdogCounter to 0x00 makes the serial port problem go away, while initializing it to 0xFF brings the serial port problem back. This is using the Arduino 1.0.3 IDE if that matters. e: Just checked with the latest version (1.0.4) of the IDE and got the same result. C++ code:
PDP-1 fucked around with this message at 16:20 on Apr 21, 2013 |
# ¿ Apr 21, 2013 16:08 |
|
TheLastManStanding posted:Opening the serial monitor resets the arduino (in the same way that pressing the reset button does) which is why your value and pin state changes briefly. A quick google search led to an arduino playground discussion on disabling the auto reset. Bingo! That was the problem, and explains all of the symptoms I was seeing. Thanks so much for this - I was totally barking up the wrong tree thinking that the serial port was mucking with timer settings, and was thinking about dumping the ROM and searching for anything that touched the Timer0 registers manually. Instead it turned out to be something really simple. evensevenone posted:Also having the device spit out "reset" on startup will save you a ton of grief. Also good advice, it helped confirm that the device really was being reset upon starting the serial monitor window. Thanks again thread!
|
# ¿ Apr 24, 2013 02:00 |
|
I've got a question about using the SPI port on an ATMega644 which is basically the Arduino chip with more IO lines so maybe you folks can help. I have the SPI port set to act as master so the slave select (*SS) pin should be available as a general use pin so long as it's configured as an output, assuming I'm understanding the documentation correctly. The problem is that it doesn't seem to want to act as an output - I configure it as an output in the appropriate DDRx register and even write an initial high output state to it, but there's no positive voltage appearing on the pin. What else do I need to do to get this pin working as an output again? Here's my SPI setup code in case it helps. The DigitalPinConfigure stuff is just my lazy way of mapping a physical pin to a port/pin# and setting the appropriate DDRx, PINx, PORTx values. It works for every other pin/port combo on the chip so I think it's OK. code:
PDP-1 fucked around with this message at 18:19 on Jul 6, 2014 |
# ¿ Jul 6, 2014 17:51 |
|
mod sassinator posted:Hrm, it seems odd to me that in master mode you would be allowed to use SS as a free GPIO pin. In SPI the SS pin is held low (or sometimes high) by the master when it initiates communication to a slave device, so having free control over it doesn't seem right. I would try to use a different pin or double check the ATmega datasheet to really confirm that you can control SS when letting the ATmega handle SPI communication. If you have multiple components connected to your SPI port you'll need more than one pin to act as SS to choose which of them you want to talk to at any given moment. Since the hardware can't know which lines you want to use for SS or which external component you want to talk to, it's up to you as the programmer to handle the SS values when the microcontroller is acting as SPI master. They turn the default SS line over to you to use as an output if you configure it as such. Or at least that's the impression I got from this: Atmel posted:When the SPI is configured as a Master (MSTR in SPCR is set), the user can determine the direction of the SS pin. Zero Gravitas posted:Ok, I'll take a crack at it. My other problem is that I need to save a calculated value in a loop to be used by the beginning of the next loop. Is there any way to do this easily or do I need to temporarily write it to the EEPROM on the chip? Couldn't you just use a variable that is outside of whatever function contains your loop to store the result between calls? Or make a static variable within the function if you don't want other parts of the program to be able to modify it?
|
# ¿ Jul 6, 2014 20:25 |
|
mod sassinator posted:Hrm, I would compare what you're doing with what Arduino's SPI code does and see what the difference might be: https://github.com/arduino/Arduino/blob/master/libraries/SPI/SPI.cpp Thanks for this. The only big difference I see is that they make their SS pin a high output before setting SPI to master mode, while I'm configuring SS as a low output. I wouldn't think that should matter but I'll give it a try next time I'm putzing around with it just to be sure. Sagebrush posted:Something I've always thought about re. EEPROM was a way to get it to only write data when the power supply fails. I thought about putting a supercapacitor (~0.1F 5v) across the power leads and probing the voltage occasionally to see if it's discharging, and if it is, write any important data to EEPROM and go into a brownout state. But you couldn't just do a standard analog compare, because that compares the incoming value to the chip Vcc, right? So you'd always have the same reading. Maybe some kind of little external RC circuit powered by the supercapacitor that you sample occasionally and compare to the chip's internal clock? Google for 'Arduino brownout detector'. The chip has an on-board system for sensing low power line voltages and notifying the software when the line gets below certain levels. Unfortunately I mainly use Atmel Studio so I don't know how to access that stuff in the Arduino IDE, but it exists on the hardware side so someone has likely written a blog post or twenty about it. e: This guy describes the process, but it looks like you need either a second arduino or an ICSP programmer unit to do it because you'll have to change some of the fuse bits. PDP-1 fucked around with this message at 21:05 on Jul 6, 2014 |
# ¿ Jul 6, 2014 21:01 |
|
How about using a gearbox/stepper motor combo? Choose a gearbox that'd give you the right amount of torque and mount it on the valve stem, then drive the stepper motor off the Arduino via an appropriate motor driver board for whatever number of steps you determine to be sufficient to turn it 90 degrees. A proper solenoid valve would be my first go-to, but you know your setup better than I do. For the lightswitch, the SSR in parallel with the existing switch that Bad Munki mentioned would be simple and reliable.
|
# ¿ May 1, 2015 16:33 |
|
mod sassinator posted:millis() An alternate method would be to set up one of the timers to count clock cycles with an appropriate prescaler to form a clock that 'ticks' once per 0.1 second. Each 'tick' would fire off an interrupt that would increment some counter variable by one. At the start of your balloon filling step you'd zero out that variable and then in the loop() function you'd check it to see if it had grown beyond some value representing a reasonable amount of time needed to fill the balloon. If the tick counter indicates that the balloon hasn't filled within a safe timeframe you could shut the physical system down to a safe state. If you don't really care about a possible bug every 49 days then just use millis() because it's way easier. If you do care about running for a long time this method would get around the 2^32 overflow problem.
|
# ¿ Sep 13, 2015 05:40 |
|
I've never actually tried doing this, but it seems like it'd be possible to 'overdrive' the servo a bit during long moves by adding your own proportional control in code. Something like this:code:
Now suppose the servo has turned for a bit and is at 45% rotation. The new overdriven setpoint is SV2 = 50% + 1.0f * (50% - 45%) or SV2 = 55%. In other words, as the servo approaches its final position the overdrive variable starts to slack off a bit. It's easy to see that when SV=PV, aka we're exactly where we want to be, SV2=SV so the overdrive isn't doing anything anymore. Basically we're adding our own proportional control loop term to the servo's internal control loop to speed it up when it's far from the desired position. To find the appropriate value for P run the servo under normal load conditions and gradually increase P until the servo starts to oscillate around the setpoint position. Throttle P back to about 70% of the minimum P value that causes oscillations.
|
# ¿ Oct 5, 2015 14:53 |
|
I'm trying to configure the INT0 interrupt to act like a one-shot edge detector that will monitor some signal IN_PIN for an upward transition and then briefly pulse OUT_PIN before going back to being quiet for a while. I stripped down my code to what is shown below, where I periodically enable INT0 in the main loop and disable it in its' own ISR to make it a one-shot. code:
As I was messing around with the code I noticed that removing the final EIMSK=0 line in the ISR caused the output pulses to line up with the positive edge transitions of the input pulses, but of course now we loose the triggerable one-shot behavior that I was hoping for: Any ideas as to what causes setting EMISK=0 to make INT0 go crazy like this? A also tried more carefully making the bits I wanted to change in case some of the reserved bits in that register were connected to something important, aka EMISK&=0xFC but it didn't change anything. e: less table-breaking images PDP-1 fucked around with this message at 19:29 on Apr 19, 2016 |
# ¿ Apr 19, 2016 17:59 |
|
JawnV6 posted:If you're comfortable enough using EIMSK registers, maybe you could skip using digitalWrite and send values directly to the pin registers instead. Also, put another (lightweight) pin write in the loop and toggle it when you're re-enabling INT0. Pull that up on the scope and see when that's occurring. Thanks for the comments. I added a second output pin to show when INT0 was getting enabled and it revealed that INT0 was firing off instantly after being turned on. I read up on how interrupts are generated and found this: So basically you have to write a 1 to the flag bits to set them to 0, as clearly spelled out on one line buried in the 660 page datasheet. I had been writing a 0 to EIFR to make it 0 like some kind of goddamn fool. Anyway, after making that one change everything is working great and one-shotting like I wanted with pretty tight timing. Captain Cool posted:EIFR bits are cleared by writing 1, not 0. It would be strange if that fixed your problem, but it's worth a shot. See, this guy read the 660 page manual cover-to-cover. It actually did fix the issue, and there doesn't seem to be much of a set-up time needed according to my scope - maybe a handful of clock cycles to finish whatever instruction is currently being processed and jump to the ISR vector.
|
# ¿ Apr 20, 2016 15:54 |
|
Yeah, shift registers like the xx595 can be hooked up directly to a SPI port and then chained in series for as many input/output ports as you could practically want. I did this for an old project where I was switching a bunch of relays to drive lights on a UI: The data in pin connects to the SPI MOSI, the shift clock is the SPI SCK signal, and the latch pin is the SPI SS*. If you want to run more than 8 bits of output, just run the data out of register #1 into the data in of register #2, etc., and tie their latch lines together. In operation you'd bring the SS line low, write N bytes out your spi port for the N registers you have chained together, then bring the SS line high and they'd all latch their new data to their outputs simultaneously. *or whatever digital output you want to use as a chip select signal
|
# ¿ Apr 26, 2016 00:47 |
|
xilni posted:Anyone know a better way to breadboard an esp8266 than this? Get something like these, break off an appropriate number of pins, solder the short end to the pcb and stick the long end in the breadboard?
|
# ¿ Apr 27, 2016 01:19 |
|
You could check out the MAX31855 family of chips and use a thermocouple as the sense element. The MAX chip connects directly to the thermocouple and delivers its readings over a SPI connection. You can get Type-K thermocouples inside of stainless steel probes for less than $10USD off Amazon. Looks like Adafruit has breakout boards for that chip too.
|
# ¿ May 20, 2016 03:38 |
|
peepsalot posted:The chinese arduino clones often use a CH34x serial converter chip, as opposed to the FTDI chip use in authentic ones. You likely need to install a driver for that serial converter if its not flashing right, but as sagebursh says the part of the message you posted so far is normal. If I could only give one piece of advice to someone just starting out with Arduinos for the first time it's to just pony up the extra $5-$10 to get an authentic version rather than a knock-off. The authentic versions are well documented and pretty much every known potential pitfall has been discussed in detail on the internet somewhere. The knock offs introduce a ton of subtle issues (like serial -> usb interface chips) that can cause infinite frustration to new people who don't have the experience to differentiate between normal and unexpected behaviors. Also that boat thing is amazing, nice job even if it was just helping out with the code!
|
# ¿ Jul 31, 2016 03:27 |
|
Are analog RC filters on the switches an option?
|
# ¿ Jan 1, 2024 16:28 |
|
|
# ¿ May 14, 2024 17:14 |
|
You can do a similar hysteresis function in hardware by having a byte for each pin that gets incremented (up to some max value) each time the button is pushed and decremented (limited to zero) when it isn't pushed. Only change the output state when the counter hits one of those limits.
|
# ¿ Jan 1, 2024 20:21 |