What changes has to be made to my original code? - embedded

I have written a code for DL1416 display it is a 4 digit 16 segments display. I need to test pd2816 display using arduino.
The pd2816 is a 8 digit 18 segments display. Can someone help me out with what changes can be made to my actual code so that I can scroll the digits in the 8 digit instead of 4 and check all the segments in the PD 2816....
DL1416 datasheet
pd2816 its datasheet is avalable here

Although I'm not sure what stopped you from reading the datasheet you linked in your question I'll answer this
The problem I am facing here is it is a 8 digit and how to scroll the
numbers into all the 8 segments
According to the datasheet you address the digit you want to write with signals A1,A2,A3 where you simply provide the bits of the desired digit.
So if you want to write the fifth digit, you provide the digit through D0-D7 and set the control inputs according to that table.
5 is 0b101 so A0 is HIGH, A1 is LOW, A2 is HIGH
You might also think about the way you set those values without >600 explicit calls to digitalWrite
Use a function that sets the outputs and store the combinations as numbers. 7 bits represent a number. So why not use that fact?
As pins 0-7 are all on one port you can even use port manipulation.
Instead of
digitalWrite(0, HIGH);
digitalWrite(1, LOW);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
You could simply write
PORTD = 0b00110001;

Related

Only scrolling some Text in 16x2 LCD(HD44780 display programm

I have a program which display as follows .
first Line : Volt : Over Voltage
Second Line : Current : Over Current.
In LCD the cant fully display the letter OVer Voltage or Over Current .
I just want to scroll these . But the Volt : and current : letter will be there that will not need to scroll ?
So you will need to create a routine to cycle thru the messages you want to display.
As an example, first time send "Volt: Over Volta"
Then a second later send "Volt: ver Voltag"
then "Volt: er Voltage" and so on.
The other option would be to create a routine to display the value part with a starting index after determining the len.
The following puesdo code is not compiled/tested.
char buf[17];
char label[]= "Current";
char value[]= "Over Current";
while(1)
{
if (++start_pos >= (strlen(value)+strlen(label)-16)
{
start_pos=0;
delay(500); //ms
}
snprintf(buf,16,"%s: %s",label,value[start_pos]);
puts(buf); // whatever the name of your routine to send string to LCD
if (start_pos==0)
{
delay(500); //ms
}
delay(1000); //ms NOTE: you probably want to go do some other code during this time.
}
You may want to see if you're LCD has a scroll command. Some LCDs have a character buffer where you can write data to then give a scroll command to shift which are displayed. For example I've used an LCD that can store 40 characters per line in DDRAM while displaying only 16. If I remember correctly, you have to scroll both lines at once this way, though.
If this doesn't tickle your fancy, another way is to shift your buffer in code and re-write all of it to the LCD. You can do this fast enough that it doesn't look terrible.

Reading incorrect temperature value from thermistor using EVK1100

I want to get the temperature from a thermistor, so I made a voltage divider (3.3V to 10k resistor and between ground a 10k thermistor) I read the ADC between the 10k resistor and the thermistor.
The BCOEFFICIENT is 3977, the NOMINAL TEMPERATURE is 25C and I use the simple B parameter equation. I'm not sure where I'm doing mistake, I read room temperature as 10.5C which was suppose to be around 24C. The following is the part of the program that I used for temperature sensor(developed in AVR studio),
#define TEMPERATURENOMINAL 25
#define TERMISTORNOMINAL 10000
#define BCOEFFICIENT 3977
#define SERIESRESISTOR 10000
{
float ke1,tempa,xin
ke1 = adc_get_value(peak_adc2,peak2);
xin=(1023/ke1)-1;
xin=SERIESRESISTOR/xin;
tempa=xin/TERMISTORNOMINAL;
tempa=log(tempa);
tempa/= BCOEFFICIENT;
tempa+=1.0/(TEMPERATURENOMINAL + 273.15);
tempa=1.0/tempa;
tempa-=273.15;
dip204_set_cursor_position(1,3);
//sprintf(ui, "Temp is %.2f deg", Ref);
sprintf(ui, "Temp is %.2f deg", tempa);
dip204_write_string(ui);
}
I checked the voltage using multi-meter for instance in between the thermistor and 10k resistor and in the EVK 1100 using the following line
ke1 = adc_get_value(peak_adc2,peak2)*3.3/1024;
I get the same voltage in both.
Not sure where I'm doing a mistake, Hope someone guide me in right direction
Your code looks correct to me, and I suspect a hardware problem may be the culprit.
It seems likely you have inadvertently connected two 10K-ohm pull-up resistors between the ADC input and the +3.3V reference: perhaps one is already populated on the EVK1100 board, and you have added another one externally connected to your thermistor. This would be equivalent to putting both 10K-ohm resistors in parallel with each other, which would be equivalent to a 5K-ohm resistor in series with the thermistor. At 25°C, the thermistor resistance Rt would read 10K ohms, which would produce a voltage of:
+3.3V * (Rt / (Rt + 5K))
= 2.20V
instead of the correct +1.65V. This number is very close to the result you are seeing (+2.17V # 24°C).
You can verify this hypothesis by looking at the schematic and/or PCB for the EVK1100 to see if a 10K-ohm pull-up resistor is connected from the ADC input to +3.3V. If this is the problem, remove one of the two resistors and you should see correct behavior.

Getting GPS to Work on SIM5320A 3G/GPS Module

I have a Adafruit FONA 3G/GPS module (American Version). I have gotten the cellular functionality to work but I am struggling with GPS. I have tried both passive and active antennas.
This is a list of AT commands that are available to the SIM5320A module (pdf). The Adafruit example code uses AT commands that don't run on this SIM module. I send the following sequence:
AT+CGPS=1,1
AT+CGPSINFO
and I am receiving:
+CGPSINFO: ,,,,,,,,
AmpI/AmpQ: 4xx/4xx
What exactly is going wrong? I am connected but am not getting any data out. Also, I understand the mathematical significance of AmpI/AmpQ but what does that mean in terms of connection to GPS network?
First, if you're using the FONATest example from Adafruit, you need to look around line 48. Comment out the line that declares a variable of type Adafruit_FONA and uncomment the line that declares a variable of type Adafruit_FONA_3G.
Also, if you haven't run the FONA_3G setbaud program to set the baud rate to something other than 115,200, you need to run it. (This isn't made very clear by Adafruit, and I thought my board was bad before I found that information.)
Second, unless you bridge the pads labeled bias on the board, you will have to use a passive GPS antenna. The SIMCOM module's GPS is pretty sensitive though. I had a uFL-to-SMA adapter plugged into the board, and stuck a 5-inch jumper wire into the SMA's center pin. The GPS acquired a position within a minute!
I tried the following command: AT+CGPS=1 and then used AT+CGPS? to query the GPS status. It reported +CGPS: 1,1 back to me.
The first few attempts at sending AT+CGPSINFO gave me the same info that you got, i.e. no position.
However, after a few minutes with a wire (or passive antenna), AT+CGPSINFO started returning valid time and position information.
Hope this helps.
UPDATE:
You've asked for code, and I'm happy to oblige. This code is designed to just be a terminal-like relay for serial data between the Arduino (using Tools -> Serial Monitor) and the Fona. So the commands I described above, I just entered by hand. Still, some folks may find it useful.
#include <Adafruit_FONA.h>
#include <SoftwareSerial.h>
#define RX_FROM_FONA 2
#define TX_TO_FONA 3
#define FONA_RST 4
#define FONA_PWR_KEY 5
#define FONA_PWR_STATUS 7
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
SoftwareSerial fonaSerial = SoftwareSerial(TX_TO_FONA, RX_FROM_FONA);
void setup() {
pinMode(FONA_RST, OUTPUT);
pinMode(FONA_PWR_KEY, OUTPUT);
pinMode(FONA_PWR_STATUS, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(FONA_RST, HIGH);
digitalWrite(FONA_PWR_KEY, HIGH);
resetFona();
Serial.begin(115200);
fonaSerial.begin(4800);
}
void resetFona() {
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_RST, LOW);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_RST, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_PWR_KEY, LOW);
delay(5000);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_PWR_KEY, HIGH);
delay(100);
}
char buffer[255];
int crIndex = 0;
int bufferIndex = 0;
int foundCR = 0;
void loop() {
if (Serial.available()) {
buffer[bufferIndex++] = Serial.read();
if (buffer[bufferIndex - 1] == 13) {
crIndex = bufferIndex - 1;
foundCR = 1;
}
}
if (bufferIndex > 255) { bufferIndex = 0; }
while (fonaSerial.available()) { Serial.write(fonaSerial.read()); }
if (foundCR > 0) {
for (int i = 0; i <= crIndex; i++) {
fonaSerial.write(buffer[i]);
}
foundCR = 0;
bufferIndex = 0;
crIndex = 0;
}
}
I don't think this is a software problem, I think you have a hardware problem.
I had this same problem. The sensitivity of the SIM5320A is pretty good, but Adafruit hasn't really followed their design guide in implementing the carrier board, and this hurts its sensitivity.
For example, you can read the application notes for the board here. Check out the PDFs on "SMT Module Design" and "Hardware Design."
First thing you'll notice is SIMCOM recommends a LC tuning network to tune your particular antenna to 50-ohm impedance.
Here is the SIMCOM recommended diagram:
And here is the Adafruit design, with no tuning network anywhere to be found:
Now, if you're going to be using this in your own PCB later, you of course are free to make improvements here yourself.
To test your design, you're going to want to know more about what the module is saying, otherwise you're flying blind. You can read the GPS NMEA sequences and decipher them, but there's a lot to it. Another way is to use the GPS demo tool that SIMCOM support offers. To download this, go to:
ftp://simcom.exavault.com/SIM5320A/GPS tool
username=myd
psd=simcommyd
It will show you how many satellites you're connected to, what signal strength they have, etc. You are going to need at least 3 satellites for a lock (technically you should have 4, but some modules will toss out an impossible triangulation solution with just 3, not sure which the SIM5320A has). You want each satellite to have strengths in the 30+ range.
Here is my Before screenshot, you can see I only had one satellite and hence no lock. This was after giving half an hour after cold start to download the almanac and ephemeris tables (will take about 15min on average from cold start). Satellite 21 (with signal of also 21 strength, coincidentally).
What I did to fix my signal gain was add an LNA (Low Noise Amplifier) in series with my passive antenna. I used the BGA524N6BOARDTOBO1 breakout board, which you can get at DigiKey/Mouser/others, and adds 19dB of gain, and an incredibly-low 0.55dB noise figure.
After hooking up my antenna, and waiting some time, I got a lock!
Hope this helps you and others to use this otherwise great module.

Arduino + OV7670 - Without FIFO - Reading Snapshot

I know that there is a lot in internet (http://forum.arduino.cc/index.php?topic=159557.0 for example) about OV7670 and I read a lot about it, but seems something is missing.
First of all I took a look into the way how can we read pixel by pixel from the camera to build the rectangular 600 X 480 image, and this was quite easy to understand considering HREF, VSYNCH and PCLOCK described on documentation here: http://www.voti.nl/docs/OV7670.pdf. I understand XCLOCK as an input I need to give to OV7670 as a kind of cycle controller and RESET would be something to reset it.
So at this point I thought that the functionality of such camera would be covered by wiring the following pins:
D0..D7 - for data (pixel) connected to arduino digital pins 0 to 7 as INPUT on arduino board
XCLK - for camera clock connected to arduino digital pin 8 as OUTPUT from arduino board
PCLK - for pixel clock connected to arduino digital pin 9 as INPUT on arduino board
HREF - to define when a line starts / ends connected to arduino digital pin 10 as INPUT on arduino board
VSYCH - to define when a frame starts / ends connected to arduino digital pin 11 as INPUT on arduino board
GRD - groud connected to arduino GRD
3V3 - 3,3 INPUT connected to arduino 3,3v
RESET - connected to arduino RESET
PWDN - connected to arduino GRD
The implementation for such approach from my point of view would be something like:
Code:
for each loop function do
write high to XCLK
if VSYNCH is HIGH
return;
if HREF is LOW
return;
if lastPCLOCK was HIGH and currentPCLOCK is LOW
readPixelFromDataPins();
end for
My readPixelFromDataPins() basically read just the first byte (as I'm just testing if I can even read something from the camera), and it is written as follows:
Code:
byte readPixelFromDataPins() {
byte result = 0;
for (int i = 0; i < 8; i++) {
result = result << 1 | digitalRead(data_p[i]);
}
return result;
}
In order to check if something is being read from the camera I just print it to the Serial 9600, the byte read from data pins as a number. But currently I'm receiving only zero values. The code I'm using to retrieve an image is stored here: https://gist.github.com/franciscospaeth/8503747.
Did somebody that makes OV7670 work with Arduino already figure out what am I doing wrong? I suppose I'm using the XCLOCK wrongly right? What shall I do to get it working?
I searched a lot and I didn't found any SSCCE (http://sscce.org/) for this camera using arduino, if somebody have it please let me know.
This question is present on arduino forum (http://forum.arduino.cc/index.php?topic=211741.0) too.
your idea is not bad but ...
the xclock need to be a clock (in your program is just a transition from 0 to 1 and is freezing there)
you need also to use I2C with SIOC and SIOD for configuring the camera (or you can use the default settings, but I am not sure if is the correct output format for you, 30F/s,VGA, YUV format ....)
your code execution is slower using the serial output in the same loop with reading data
I will recommend you to toggle the xclock pin and to move the pixel print in a if(). Also you will be able to read Data only in a very precise time, if you want to read only one byte, than after a transition from 0 to 1 of HREF you need to wait for a new transition from 0 to 1 of PCLK (you will be able to see only one 0-1 transition of HREF after 784x2 transitions of PCLK, (640 active pixels + 144 dead time for each line) x 2 (for YUV or RGB are 2 bytes received for each pixel) )
Hello I am Mr_Arduino from the arduino forums. Your issue is that you are reading pixels too slow please do not use digital read to do such a thing. Also if you insist on using a separate function just to read a byte make sure the function is being inlined. You can do this by declaring your function as static inline. Also as mentioned above how are you generating the clock. You can generate the XCLK using PWM on the arduino.
I have created a working example here:
https://github.com/ComputerNerd/arduino-camera-tft/blob/master/captureimage.c
Edit: a 3rd party has copied part but not all of the code from the above link into the answer here. However, the link must remain as the code posted below requires additional files from that source to actually work.
Edit 2: Removed irrelevant code. You will need to modify what you do with the data.
void capImg(void){
cli();
uint8_t w,ww;
uint8_t h;
w=160;
h=240;
tft_setXY(0,0);
CS_LOW;
RS_HIGH;
RD_HIGH;
DDRA=0xFF;
//DDRC=0;
#ifdef MT9D111
while (PINE&32){}//wait for low
while (!(PINE&32)){}//wait for high
#else
while (!(PINE&32)){}//wait for high
while (PINE&32){}//wait for low
#endif
while (h--){
ww=w;
while (ww--){
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
WR_LOW;
while (PINE&16){}//wait for low
PORTA=PINC;
WR_HIGH;
while (!(PINE&16)){}//wait for high
}
}
CS_HIGH;
sei();
}
You can also find it on github.
You can use my instruction: how to retrieve image from ov7670 It contains all the steps you need. There is also instuction to setup FrameGrabber: how to run framegrabber

How I can fix this code to allow my AVR to talk over serial port?

I've been pulling my hair out lately trying to get an ATmega162 on my STK200 to talk to my computer over RS232. I checked and made sure that the STK200 contains a MAX202CPE chip.
I've configured the chip to use its internal 8MHz clock and divided it by 8.
I've tried to copy the code out of the data sheet (and made changes where the compiler complained), but to no avail.
My code is below, could someone please help me fix the problems that I'm having?
I've confirmed that my serial port works on other devices and is not faulty.
Thanks!
#include <avr/io.h>
#include <avr/iom162.h>
#define BAUDRATE 4800
void USART_Init(unsigned int baud)
{
UBRR0H = (unsigned char)(baud >> 8);
UBRR0L = (unsigned char)baud;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
unsigned char USART_Receive()
{
while(!(UCSR0A & (1 << RXC0)));
return UDR0;
}
int main()
{
USART_Init(BAUDRATE);
unsigned char data;
// all are 1, all as output
DDRB = 0xFF;
while(1)
{
data = USART_Receive();
PORTB = data;
USART_Transmit(data);
}
}
I have commented on Greg's answer, but would like to add one more thing. For this sort of problem the gold standard method of debugging it is to first understand asynchronous serial communications, then to get an oscilloscope and see what's happening on the line. If characters are being exchanged and it's just a baudrate problem this will be particularly helpful as you can calculate the baudrate you are seeing and then adjust the divisor accordingly.
Here is a super quick primer, no doubt you can find something much more comprehensive on Wikipedia or elsewhere.
Let's assume 8 bits, no parity, 1 stop bit (the most common setup). Then if the character being transmitted is say 0x3f (= ascii '?'), then the line looks like this;
...--+ +---+---+---+---+---+---+ +---+--...
| S | 1 1 1 1 1 1 | 0 0 | E
+---+ +---+---+
The high (1) level is +5V at the chip and -12V after conversion to RS232 levels.
The low (0) level is 0V at the chip and +12V after conversion to RS232 levels.
S is the start bit.
Then we have 8 data bits, least significant first, so here 00111111 = 0x3f = '?'.
E is the stop (e for end) bit.
Time is advancing from left to right, just like an oscilloscope display, If the baudrate is 4800, then each bit spans (1/4800) seconds = 0.21 milliseconds (approx).
The receiver works by sampling the line and looking for a falling edge (a quiescent line is simply logical '1' all the time). The receiver knows the baudrate, and the number of start bits (1), so it measures one half bit time from the falling edge to find the middle of the start bit, then samples the line 8 bit times in succession after that to collect the data bits. The receiver then waits one more bit time (until half way through the stop bit) and starts looking for another start bit (i.e. falling edge). Meanwhile the character read is made available to the rest of the system. The transmitter guarantees that the next falling edge won't begin until the stop bit is complete. The transmitter can be programmed to always wait longer (with additional stop bits) but that is a legacy issue, extra stop bits were only required with very slow hardware and/or software setups.
I don't have reference material handy, but the baud rate register UBRR usually contains a divisor value, rather than the desired baud rate itself. A quick google search indicates that the correct divisor value for 4800 baud may be 239. So try:
divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;
If this doesn't work, check with the reference docs for your particular chip for the correct divisor calculation formula.
For debugging UART communication, there are two useful things to do:
1) Do a loop-back at the connector and make sure you can read back what you write. If you send a character and get it back exactly, you know that the hardware is wired correctly, and that at least the basic set of UART register configuration is correct.
2) Repeatedly send the character 0x55 ("U") - the binary bit pattern 01010101 will allow you to quickly see the bit width on the oscilloscope, which will let you verify that the speed setting is correct.
After reading the data sheet a little more thoroughly, I was incorrectly setting the baudrate. The ATmega162 data sheet had a chart of clock frequencies plotted against baud rates and the corresponding error.
For a 4800 baud rate and a 1 MHz clock frequency, the error was 0.2%, which was acceptable for me. The trick was passing 12 to the USART_Init() function, instead of 4800.
Hope this helps someone else out!