I purchased a 2-pack of rip off NES 8bit controllers on Amazon with an “extension” cord so that I had a ready made connector. Cut the extension cord off and wired it to an Arduino Mega (because that’s what was on the bench). I am using this for a game I am working on for the Makerspace… but through maybe you could use a snippet that worked. The first google code I tried to copy and paste didn’t work so hot.. so here is what I came up… I did find some inspiration here and there but this is a good launching point for your next project.
/*
NES Controller
*/
const int latch = 50;
const int clock = 48;
const int data = 49;
#define latchlow digitalWrite(latch, LOW)
#define latchhigh digitalWrite(latch, HIGH)
#define clocklow digitalWrite(clock, LOW)
#define clockhigh digitalWrite(clock, HIGH)
#define dataread digitalRead(data)
#define wait delayMicroseconds(15)
unsigned long previousMillis = 0;
const int wait_interval = 20;
const int A_BUTTON = 0;
const int B_BUTTON = 1;
const int SELECT_BUTTON = 2;
const int START_BUTTON = 3;
const int UP_BUTTON = 4;
const int DOWN_BUTTON = 5;
const int LEFT_BUTTON = 6;
const int RIGHT_BUTTON = 7;
byte output;
void setup() {
Serial.begin(115200);
pinMode(latch, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(data, INPUT);
Serial.println("NES TEST");
}
boolean isBitSet (byte myVar, byte bitNumber) {
bool bitvalue;
bitvalue = myVar & (1 << bitNumber);
return bitvalue;
}
void readNES() {
latchlow;
clocklow;
latchhigh;
wait;
latchlow;
for (int i = 0; i < 8; i++) {
output += dataread * (1 << i);
clockhigh;
wait;
clocklow;
wait;
}
}
void hexprint(byte b) {
Serial.print("0x");
if (b < 10) Serial.print("0");
Serial.println(b, HEX);
}
void loop() {
output = 0;
readNES();
if (!isBitSet(output, 0)) Serial.println("A Button");
if (!isBitSet(output, 1)) Serial.println("B Button");
if (!isBitSet(output, 2)) Serial.println("SELECT Button");
if (!isBitSet(output, 3)) Serial.println("START Button");
if (!isBitSet(output, 4)) Serial.println("UP Button");
if (!isBitSet(output, 5)) Serial.println("DOWN Button");
if (!isBitSet(output, 6)) Serial.println("LEFT Button");
if (!isBitSet(output, 7)) Serial.println("RIGHT Button");
//Serial.print("Read: "); hexprint(output);
}
I thought I’d drop this here for someone who needed a copy-paste solution.
I am parsing a serial string output from a YDLIDAR X4 rotating lidar. I have to do this because the library sucks. a lot. I mean I’m not over my heels with the unit anyhow, first off who the hell outputs at 128,000 baud? I’ll post the code when it’s done enough for someone to build off of it.
I was getting an error in number of bytes in the packet as parsed from the serial string so I had to break out the function into really busy but obvious code to see where I was going wrong. The code has me concatenating two bytes and an upper nibble. Ignore the discrepancy in how I added my bytes backwards in my code vs. how the device actually stacks it’s data… because you know: WHO IN THEIR RIGHT MIND SHIFTS LSB ON THE LEFT?! (note the “length bytes as shown in 12 bits and the “response length” example below.)
Anyhow… feel free to show me how to do it better in the comments. Obviously this is built for you to look at it do it’s magic in a serial monitor.
What a groaner.. who needs another datalogger? Well I do, so stuff it. I was inspired to check out these iButtonLink devices that allow you to daisy-chain connect a number of devices in a single circuit of sorts with RJ45 patch cables. I had seen these a couple years ago in some top-notch datacenters that terminated to a concentrator (4 strings) that were then pushed up to some IBM services app server.
A while back I published a Microsoft PIC microcontroller version of this … I decided to give it another whirl with the “easy button” … Arduino. Of course there were a couple libraries that I just had to collectively stuff into the same sketch and easy-peasy it was done in an hour or so.
This time I have my data stored to an SD card, which … I hastily put together.
If I was actually going to finish this I would add three things to this to finish it up.
Use an RTC, figure an interface to enter the correct time. (maybe add an ethernet shield and get NTP?) … or just manual enter.
I’d grab the interval time off the RTC and just have the loop do a non-blocking wait, then poll the RTC time or interrupt (whatever you favorite way to do this is..) that way I was collecting trend information on the “:00″s.
I would add a method of checking for an SD card to be interested and allow it to start logging from card insert. I would also add time/date stamp to the file and finally, still SD card related I would check file size and stop logging when I got close to full.
So that is that. I’ve been creating a lot of fun lately but nothing mind-bending.. just going through every module I’ve ever bought doing the demo code … or going the other way around.. working on every Arduino demo/example in a class .. I’ve also built an FE boat, moved my workshop inside (update video coming kind of soon) and been working on PopBot 0.5 ..
The code:
/*
* Chas Ihler
* @chasxmd
* https://iradan.com
*
* License: Public Domain - it's mostly copy and paste and preferences anyways.
*
* iButtonLink, grabs all sensors and logs them to card if present.
* Recommendations:
* Add an RTC and a method of updating time.
* I'd also grab actual seconds off the RTC for logging and use a non-blocking wait for the polling/logging.
*
* Libraries:
* https://github.com/matmunk/DS18B20
* IDE built in SD card/SPI library
*
* Sensor:
* https://www.ibuttonlink.com/products/t-sense-temperature-sensor
* which has this device within..
* https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
*
* Hookup:
* You'll need a pullup resistor from 5V to pin 2
* ibutton hookup:
* 1 - GND
* 2 - 5VDC
* 3 - NC
* 4 - Arduino Pin 2 (w/ Pullup)
* 5 - GND
* 6 - NC
* 7 - NC
* 8 - NC
*
* SD card attached to SPI bus as follows:
* MOSI - pin 11
* MISO - pin 12
* CLK - pin 13
* CS - pin 4
*
*/
#include <DS18B20.h>
#include <SPI.h>
#include <SD.h>
DS18B20 ds(2); //pin 2
const int chipSelect = 4;
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("----------------------------------------");
Serial.println(" ");
Serial.println("DS18B20 / iButtonLink Demo");
Serial.print("Devices: ");
Serial.println(ds.getNumberOfDevices());
Serial.println(" ");
Serial.println("----------------------------------------");
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
}
void loop() {
int i_address;
Serial.println("----------------------------------------");
while (ds.selectNext()) {
String str_dataString = "";
switch (ds.getFamilyCode()) {
case MODEL_DS18S20:
Serial.println("Model: DS18S20/DS1820");
break;
case MODEL_DS1822:
Serial.println("Model: DS1822");
break;
case MODEL_DS18B20:
Serial.println("Model: DS18B20");
break;
default:
Serial.println("Unrecognized Device");
break;
}
uint8_t address[8];
ds.getAddress(address);
Serial.print("Address:");
for (uint8_t i = 0; i < 8; i++) {
Serial.print(" ");
Serial.print(address[i]);
str_dataString += String(address[i]);
}
Serial.println();
/*
Serial.print("Resolution: ");
Serial.println(ds.getResolution());
Serial.print("Power Mode: ");
if (ds.getPowerMode()) {
Serial.println("External");
} else {
Serial.println("Parasite");
}
*/
Serial.print("Temperature: ");
Serial.print(ds.getTempC());
Serial.print(" C / ");
Serial.print(ds.getTempF());
Serial.println(" F");
str_dataString += ",";
str_dataString += String(ds.getTempC());
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(str_dataString);
dataFile.close();
Serial.println(str_dataString);
} else {
Serial.println("error opening datalog.txt");
}
Serial.println(" ***** ");
Serial.println();
}
delay(30000);
}
Using a PIC Microcontroller to pull temperature of iButtonLink T-sense sensor.
I pulled this off the wayback machine because I lost this post in the great database loss of how ever many years ago. I’m re-posting because I’m working on an expanded version of this with an Arduino dev board and wanted a reminder of what I did five years ago. Originally posted 1/2/2015. No edits.
—————————————————————————————————————-
I came across a stash of iButton T-sense 1-wire sensors.. so I grabbed a couple and decided to check out 1-wire.
Maxim makes a 1-wire device called the DS18B20. It’s a 9-12 bit temperature sensor with the possibility of being powered by parasitic power from the data line. This cuts the signal path down to a single DQ line and a return. A company called iButtonLink produces a nice little wrapper around this device called a T-Sense. There are a couple pieces of software out there that will allow you to hook these up to monitoring systems, I don’t have any though. These devices come with a 64-bit address code and can be daisy-chained which makes having many of these devices monitored very nice.
At first I thought, ugh.. lame I have to send, and parse 64-bit codes in a little 8 bit micro.. doesn’t sound like a ton of fun for just fooling around on a day off.. thank fully they have a “Skip ROM” feature/command which works similar to a broadcast but can only be used when you have one device on the bus. If there is one thing left in this project I might consider finishing it’d be to add the addressing in and daisy-chain a few of these.
For my circuit I hooked up 5VDC (but later ran it on 3.3V just fine) and the 5VDC return on pins 1 & 2. Then the DQ link and return on pins 4&5. The signaling is interesting as the 1-wire bus needs a weak pull and works with an open collector circuits. The master starts all signaling, writes and reads. The 1’s and 0’s are based on how long the master or slave sinks the DQ line. To accomplish this in the PIC microcontroller I switched the port from an output to a three state input when I needed the port to be in weak-pull up mode (which is also hand when I need to sample the port for a response from a slave). The pull up on the resistor in my circuit is 10Kohm but I’ve seen 4.7KOhm and I’m sure anywhere in the neighborhood is fine. Finally if you do some digging you’ll notice I run this in low speed mode, if I remember correctly the “high speed” mode is 4x faster. I don’t think speed of data transfer is really relevant when you’re waiting for 750ms for a temperature conversation though.
I initially started with just determining if there was a 1-wire device on the bus. If you perform a “reset” (master sinks the bus low for 480us then releases to hi-z for 70us and then performed a sample.. any (all) device(s) will sink the line slow to prove their presence…then another 410us of delay before continuing. I got this one first try.. better luck than my first time with I2C! I then wrote the code (including sampling tidbits of Microchip AN1199 code to optimize) to do an actual temperature conversion and request it (by commanding a “read scratch pad”). The device dumps all 9 bytes of it’s registers. On that note I just remembered I should mention I did NOTHING with the CRC byte.. that’s all you if you care.
My temperature conversion code looks like this: (bus control m = master or PIC, s=slave or sensor)
m RESET
s PRESENCE flag
m SKIP ROM (0xCC)
m CONV TEMP (0x44)
m HOLD DQ (Hold line high 750ms for 12bit conversion .. I am guessing we hold it high for the parasitic power supply)
m RESET
s PRESENCE flag
m SKIP ROM (0xCC)
m READ SCRATCHPAD (0xBE)
s 9 Bytes of Data
The 12-bit conversion is basically 0.0625 deg C for every bit from 0C, The LSB holds a temperature sign.
The output of my program looks like..
There are tons of details on what a “1” is an what a “0” is, the ROM code (READ ROM, MATCH ROM), changing the configuration to 9bit for 94 ms conversions over 12bit 750ms conversions. This is all stuff you can grab out of the DS18B20 specification sheet or AN1199.
I hope you get some use out of this.. I still have enough of these T-Sense modules.. maybe if someone really wants one I’ll drop it in the mail… or perhaps we can set up a big box of electronics to ship around and I can dump some in there.
Quick version: Hey this little thing works and seems practical for robotics, specifically the Pop Can Challenge.
I had to add “mini” to the title of this post, calling this a vacuum pump seems odd when you’ve played around with big pumps. Which leads me to make a mental note to share some information my industrial vacuum pump sometime; my big pump is currently at the SnoCo Makerspace but it seems it gets used as hold-down weight on glue-ups more than it’s intended use but at least it’s getting some love.
I moved workshops; I swear this is related… The kids are at an age were it’s hard for me to get out to my workshop for very long and Melissa works in the evenings right now so I just wasn’t getting any fun-stuff done. I’ll shoot another workshop video… soon-ish. I’ve been slowly filtering through my bins of incomplete or never-started projects in and sorting through it all to bring some organization into my “inside workshop”. In digging through the bins I recently came across most of this eBay purchase: https://ebay.us/2L8SOa . If you want to skip on clicking the link it’s a small motor/vacuum pump with a suction cup grabber. I bought this for PopBot after the 2019 Robothon. I put this aside because I’ve been working on PopBot and a second marine-based robot platform for the last two months. PopBot is getting a deep drive because the SRS Robothon (2020) https://robothon.org/ has been cancelled this year. The thought is I might be able to grab the PopCan with a suction cup instead of actively grabbing it, or in my case I was going to sort hug it/lasso the pop can; time will tell on this. My initial concern is current draw, thankfully thing only pulls a couple hundred milliamps and then it’ll hold it’s suction fairly well for a while. I noticed a solid drop off in current after the suction was “successful”. I would have thought it opposite but I guess based on looking at current curves on squirrel cage fans and seeing them unload without air flow I’ll accept it without figuring out why. My goal is to grab the can with a pair of suction cups, drop the motor PWM or turn it off once the suction is maintained (as determined by current) and then just provide a couple moments of pumping to maintain suction while transporting the can. For testing I came up with a quick little circuit with a Pololu DC motor driver (#2961) and an Adafruit i2c IN219 current sensor breakout board… don’t mind all the other stuff strapped to the MEGA in the photo below. It was on my bench for some sensor fusion testing. The INA219 is hooked up to the i2c ports (20/21) on the MEGA2560 and the motor driver is getting a PWM drive from Pin 6. I didn’t need to use the enable or direction, I just sunk the enable low. The amount of suction is quite adequate if you’re a 14 year old boy trying to get popular by giving yourself a hickey…. this is not recommended of course and mostly a guess as I have 4-day-old vacation stubble so there is no sense in trying.
The code for testing is at the end of the post, anyone with a couple hours of experience with Arduino IDE could whip this out in 10 minutes but just in case you were hoping to save 9-1/2 minutes…
The story: I hit a break wall with ODrive. ODrive is an open source brushless DC motor (BLDC) driver built with robotics in mind (my application..). I don’t have faith in the project and after months of trying to make it fit my application I’m abandoning it. It’s painful to spend that kind of money on a product (two even!) … but I’m not hopping back on the Stepper bandwagon just yet. I’ll see if I can put my brushless DC motors to use on PopBot 0.5.
First step was deciding on if I could use an off the shelf ESC or buy one. I purchased a RC “rockcrawler” driver as I assumed the firmware would be most compatible with my application. The car and boat ESCs have forward and reverse speed by splitting the PWM servo input in half. While waiting on shipping I found an ESC for a boat and a few for quads in one robot junk bins. Quads are single directions but the boat one was good enough for testing. It had no torque in the low end but that’s not a surprise based on the application with the motor type. I needed a way to program this ESC without a controller and receiver. Programming is typically performed w/ the receiver/controller by pushing the speed to min-max in a certain order. Well that can be done with the arduino of course. Here is a super simple piece of code for you if you don’t want to reinvent the wheel. This will also allow you to control your ESC once it’s programmed and you can uncomment my basic acceleration code if desired.
Hook up the ESC control signals (servo input). On the ESC the white (signal in, sometimes I think the alternate color is orange?) to digital output 9 on the Arduino Uno or Mega. Tie the black (or brown) wire to one of the grounds. DO NOT HOOK UP RED. We don’t need the power from the ESC.. it’s usually not something we want anyways (like 6V… ).
You’ll need this library. Download it and place the uncompressed directory in your Arduino libraries directory.
/*
* Charles Ihler, iradan.com
* 2020-04-27 build from example of library.
*
* Open the serial monitor... enter 0 (and enter) for reverse
* 1 for foward and 2 for idle/stop..
* Most ESCs want a motor hooked up or warn of damage.. make sure the motor is safe and can't spin off and hurt something.
*
*/
#include <Servo.h>
#include "ESC.h"
ESC esc(ESC::MODE_FORWARD_BACKWARD);
int sel = 0;
String ssel;
void setup()
{
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
esc.attach(9); //change to some other PWM pin if required
}
void output_high() {
digitalWrite(LED_BUILTIN, HIGH);
esc.setDirection(ESC::FORWARD);
esc.setSpeed(500); //comment this out and uncomment below for acceleration. When test running motor.
//for (int i = 0; i <= 150; i++) {
// esc.setSpeed(i);
//delay(25);
//}
}
void output_low() {
digitalWrite(LED_BUILTIN, LOW);
esc.setDirection(ESC::BACKWARD);
esc.setSpeed(500); //comment this out and uncomment below for acceleration. When test running motor.
// for (int i = 0; i <= 150; i++) {
// esc.setSpeed(i);
// delay(25);
//}
}
void output_n() {
digitalWrite(LED_BUILTIN, LOW);
esc.setDirection(ESC::BACKWARD);
esc.setSpeed(0);
}
void loop()
{
Serial.print("Forward (1), Reverse (0), Stop/N(2)?(1/0/2): ");
while (Serial.available() == 0) {}
ssel = Serial.readString();
Serial.print(" --> ");
Serial.println(ssel);
sel = ssel.toInt();
if (sel == 1) {
output_high();
Serial.println("ON!");
}
if (sel == 0) {
output_low();
Serial.println("OFF.");
}
if (sel == 2) {
output_n();
Serial.println("Neutral");
}
delay(100);
}