I am somewhat of a beginner in this space
I am using Arduino Mega2560 and interfacing it with a coin machine from a vending machine.
The coin machine runs on a protocol called MDB (multi-drop bus) which is 9bit serial.
I would normally use the Arduino IDE but that does not cater for 9-bit serial. I have therefore decided to code using c and ubuntu 12.04. I have come across a usart setup function which can bitbash into 9bit mode.
I have installed avr-gcc avr-libc avrdude.
The coin machine acts depending on serial data it recieves. i.e to reset it needs to read 100101010 from its Rx (this is a random 9-bit number, I am not sure what the true number is at this moment).
Another example would be if it recieves 10101111 on Rx it would dispense a coin of desired type etc.
There are also various other commands like ack,poll, etc.
So what I want to do is send the appropriate binary numbers out from the Arduino's Tx and into the coin machine's Rx and try get communication with the coin machine.
This was just for context but my main question is more general (lets assume we are working in 8bit mode):
a) how can I type a 8bit binary number (e.g 10111010) on the terminal, and have that number be put on the Tx line of the arduno.
b) since the mega2560 has 3 Tx/Rx modules, can I Tx from one module and Rx from another module, for testing, such that the 8bit binary number I type in terminal appears on the terminal too.
note: The reason I want the numbers to be represented in binary is because I want to see each bit, it will make more sense to me that way
I am trying to do something similar to Bouni's MateDealer (see github repository)
but he is implementing the Arduino as a slave, I want to implement as a master.
More on his project here.
Thank you kindly!
A) There is two solutions:
you send the binary representation of the number, like '00001111' through the serial line, and then in the µC you use the function strtoul, which takes as parameters an array of char (in this case '00001111') and the base (here 2) and returns the corresponding value (here 0x0F, or 16);
you create your own terminal, which converts the input binary representations into decimal representations (here, converts '00001111' into '16'), sends to the µc which uses the function atoi to get the corresponding value (here, 16 or 0x0F)
I think that the former will be easier, but a little bit slower, while the latter could offload the microcontroller.
Related
I'm writing a few kernel modules (as part of porting Linux to a new ARM board).
Most of what I want to expose to userspace fits nicely into the /sys/class/gpio and /sys/class/leds subsystems.
I have a couple of 12 bit ADCs which I want to expose to userspace.
Which subsystem should I use for this?
(Worst-case is exposing them as a character devices which stream the values as newline separated decimal values. The two ADCs are part of a multi-function-device, accessed over an i2c bus by reading two 16-bit registers.)
I tried returning 42 from a gpio module's gpio_chip.get function pointer, but it was changed to 1 by the time it reached userspace.
Is it possible to use the COM port on a linux box to read the value of a switch? I think that it should be possible with ioctl(), but i have struggled a little to find a comparable example. I only need one input, and only need it to read in a HIGH/LOW value. I thought I could just use ioctl to set one of the pins high, and wire a switch between that and another pin, again using ioctl to read the value of the second pin()
The rationale is that I have a trusty old server running in the garage, I'd like to make something that would bleep and tell if the garage door is open, Since the server sits next to the door, I thought it would be simple to just wire a switch into the back of the com port (which is currently unused)
Granted, I could spend a few pounds, save myself a headache and use an arduino or an ESP8266, but this has now got me curious!
Yes, sure you can do this. There are a number of lines on the serial port that can be used as GPIO. One of them (on pin9 I think) is RING which is used on old serial modes to signal incoming calls.
You can read it like this:
unsigned mask = TIOCM_RNG;
unsigned status;
int fd; // your serial port file descriptor.
/* Get current status of the control lines in mask */
if (ioctl(fd, TIOCMGET, &status) == -1) {
perror("ioctl(TIOCMGET)");
}
/* now evaluate status */
You also need to generate a voltage that you can apply to the ring line. One cheap way to do this is to transmit some stream of alternating bits. E.g. send 0x55 at any baud-rate.
You can then tap the voltage from the TX-pin. Split the positive and negative voltages using two diodes and buffer them using two capacitors. That will give you positive and negative voltages compatible with the ring-line.
Here is a schematic that should work. Adjust diodes and capacitors to taste, but don't go crazy with the capacitor. 10µF should be the maximum.
I have developed an embedded solution which communicates over a Multi Drop Bus and now I would like to develop a PC based application which monitors traffic on the bus.
MDB supports true 9 data bits (plus start/stop/parity - and *no fudging* by using the parity bit as a 9th data bit) whereas standard Windows and Linux libraries offer a maximum of 8 data bits.
I have a StarTech PCI2S950 PC serial port card which supports 9-data bits, but am not sure how to code my monitoring app & have googled a lot to no great avail.
I would prefer to code in C (or Delphi, or C++). I have a slight preference for Cygwn, but am willing to use straightforward Windows or Linux.
Just anything to read/write 9 data bits over that PC serial port card.
Can anyone help?
The document at http://www.semiconductorstore.com/pdf/newsite/oxford/ox16c950b.pdf describes the differences between various UARTs.
While your StarTech board includes the 16C950, which is RS-485 (and 9-bit) capable, it uses it in RS-232 compatible (550) mode, similar to 16550/8250 from IBM-PC days, and supports max 8 bit data.
You need a board with the same chip (16C950) but that exposes the RS-485 compatible 950 mode that supports 9 bit data as per the spec. And any board claiming such support would have to come with custom drivers for Windows, since Microsoft's is 8 bit only.
There are several other chips that can do 9-bit RS-485 mentioned here but again finding Windows driver support will be tricky. And, of course, many boards use 16C950 but only in 8-bit and/or RS-232 only mode, and without appropriate drivers.
In answer to your related question on Superuser, sawdust suggested the Sealevel 7205e, which looks like a good choice, with Windows driver support. It is pricey but they specifically mention 9-bit, RS-485 support, and Windows drivers. It may well be your best option.
The card you selected is not suitable for this application. It has just plain RS-232 ports, it is not suitable for a multi-drop bus. You'll need to shop elsewhere for an EIA-485 style bus interface, you could only find those at industrial electronics suppliers. By far the best way is to go through the National Automatic Merchandising Association, the industry group that owns the MDB specification.
The 9-bit data format is just a trick and is used in the MDB protocol to mode-switch between address bytes and data bytes. All ports on the bus listen to address bytes, only the addressed port listens to data bytes.
The 9th bit is simply the parity bit that any UART can generate. The fundamental data size is still 8 bits. An UART auto-generates the parity bit from the way it was initialized, you can choose between mark, space, odd and even parity.
Now this is easy to do in a micro-controller that has an UART, the kind of processor used on a bus like this. You simply re-program the UART on-the-fly, telling it to generate mark parity when you send the address bytes. And re-program it again to space parity when you send the data bytes. Waiting for the fifo to empty will typically be necessary although it depends on the actual UART chip.
That is a lot harder to do on a regular Windows or Linux machine, there's a driver between the user mode program and the UART. The driver generates a "transmit buffer empty" status bit, like WaitCommmEvent() for EV_TXEMPTY on Windows, but this doesn't include the fifo empty status, it only indicates that the buffer is empty. A workaround would be to wait for the buffer empty status and then sleep() long enough to ensure that the fifo is emptied. A fifo is typically 16 bytes deep so sleep for 16 times the bit time. You'll need the datasheet for the UART on the card you selected to know these details for sure.
Under Win32 serial ports are just files, so you create a handle for it with CreateFile and then use a DCB structure to set up the configuration options (the members are documented here and include number of data bits as ByteSize).
There's a good walk through here:
http://www.codeproject.com/Articles/3061/Creating-a-Serial-communication-on-Win32
The link provided shows the card supports 9 data bits and Windows 8, so I would presume all the cards features are available to the application through the standard Windows API.
Apart from setting the correct data format in a DCB and opening the port, I would have thought the standard ReadFile would work. I wonder if the data read in would actually be 2*8 bit bytes which represent the 9 data bits, rather than a continuous 9 bits streamed in (which you will need to decode at a later date).
Is the 9th bit used for some purpose other than data?
i'm currently using DS89C450 MCU on Keil C51 Programming.
I have an Infrared Receiver attached to P3^2 which is the falling edge trigger. Whenever I press a key on the remote control, it will trigger the interrupt and save it into the xdata X or Y (bit by bit then byte by byte for 500 bytes).
I'm trying to transmit the data bit (either '1' or '0') from the buffer to the hyperterminal via Serial Port. However, I do not get any data displayed when I press the remote control.
Can anyone expert tell me why and how do i get it to work?
The program is here:
http://pastebin.com/hpAw2ipH
Google "Terminal by br#y", it can show serial comms in HEX. Most UARTs cannot send a single bit, rather they will send a character of N bits, usually 7 or 8, with start/stop/parity bits (8-bits, no parity, 1 stop bit being the universal default). It can make life easier to encode data as ASCII, perhaps even with start/stop characters, so you know when you're getting real data.
For even more detail, use an oscilloscope, BusPirate or LogicSniffer (from DangerousPrototypes.com) to sniff the communications data.
I'm trying to write to my lpt register with the function outb(0x378,val);
well.. I tried to debug with the call int ret=inb(0x378); I always get the ret=255 no matter what value I insert with outb before.
*I'm writing on the kernel mode since my program is a driver, therefore I didn't use ioperm() etc.
thank you in advance.
You have the parameters of outb function wrong, correct order is :
outb(value, port)
so you have to change your code to do:
outb(val, 0x378)
For more details please read Linux I/O Programming Howto .
Do you know for a fact that you have a parallel port installed at that address?
Get yourself a small low-current LED. Stick the long end in one of pin 2 (LSB) to pin 9 (MSB) and the short end in pin 25 (ground).
Try writing various values and see if you can get the LED to change by the bit value of what you write.
This should work (unless as previously mentioned you've gotten it programmed in an input mode) Being able to read back the port value is less certain, depending on the type of parallel port and implementation details (for example, you probably couldn't with the buffer chip that implemented it in the original PC)
Also note that most USB "printer" adapters don't give you bitwise register access. Something hanging off of the PCI or PCMCIA, etc may also have problems with direct register access at the legacy port address. There are nice USB parallel interface chips such as the FT245 and successors which you can use if you don't have a "true" parallel port hanging off the chipset available.
Have you set the direction register? If it is set as input then you will read what is on the port.
inb(0x378) is not required to return what was written; at least I've seen chips to behave so. Well, since you, at some point, have called outb, you know what's on anyway.