Pages: 1 2 [3] 4 5 ... 19   Go Down
Author Topic: NTSC video out library  (Read 31791 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

how would i use your lib to output data from a ds18b20 temp sensor? here is the code i have but it wont compile

Code:
#include <TVout.h>
#include <OneWire.h>
#include <DallasTemperature.h>
float tempc , tempf;
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
TVout TV;
unsigned char x,y;

void setup()  {
  x=0;
  y=0;
  TV.start_render(_NTSC);
   sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); // Send the command to get temperatures
  tempc = sensors.getTempCByIndex(0);
  tempf = tempc*1.8+32;
  TV.delay_frame(60);
  TV.clear_screen();
  TV.print_str(0,0,tempf);
  TV.delay_frame(60);
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Cool 4rdu1n0
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very cool.. testing...  smiley-cool
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Cool work! I've been looking for exactly this for months, but the nearest thing I could find wasn't able to separate timer code from the main code. I've already tested this library and found perfect image and enough resolution, but I'd like to go further, adding OSD capabilities.

I think it can be done obtaining the vertical sync pulse from the video in with LM1881, and waiting for it with a while() statemente before the vertical sync signal starts in the code. As reading a pin with port manipulation takes 1 cycle (62.5 us), it will be necessary to modify the number of cycles the vertical sync takes.

What do you think? Thanks anyway for this fantastic code!
Logged

Michigan, US
Offline Offline
Full Member
***
Karma: 3
Posts: 148
Go Huskies
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ABC-king,
I cant really help much without seeing what the compiler is saying so maybe post its output?

Lover,
Using an LM1881 maybe possible.  If the LM1881 could be used the feed the arduino with logical values then a simple interrupt routine could be used to count lines, and on vsync reset that count.

The problem i see with a while loop is consistency not speed. if we are even one cycle off(not all instructions take 1 cycle) when outputting the data to the screen it will show up as jitter.  If there is no work that needs to be done the while loop could just keep the arduino asleep (this is simple if you need to know how i can show you) and use a pin change interrupt to do said counting.  By keeping the cpu asleep we can guarantee the the same time is taken to draw.  Alternatively using a timer would allow us to sync to it before outputting (my code does this to output wait_until() in video_gen.cpp).

I have found using the facilities of the mcu to be the easiest option.
As originally I wrote the library almost entirely in software and only used the timers to give me the start of each line.  While I did get an image it used up lots of cpu time and never synced correctly.
« Last Edit: May 12, 2010, 01:44:21 pm by mdmetzle » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 69
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

this is what i get when i try to compile it

Code:

 In function 'void loop()':
error: no matching function for call to 'TVout::print_str(int, int, float&)'C:\Users\brad\Desktop\arduino-0018\arduino-0018\libraries\TVout/TVout.h:78: note: candidates are: void TVout::print_str(unsigned char, unsigned char, char*)
Logged

Michigan, US
Offline Offline
Full Member
***
Karma: 3
Posts: 148
Go Huskies
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok you get this because print_str only takes a string as an argument.
to convert the float to a string try something like this:
first you need to include the stdio library:
#include <stdio.h>

define the a buffer(global variable like temc or tempf):
char buffer[20];

now replace this line:
TV.print_str(0,0,tempf);

with these:
sprintf(buffer, "%f", tempf);
TV.print_str(0,0,buffer);


I haven't built a function that will print ints, or floats. but sprintf will build a string and put it in a buffer out of anything you can throw at it if you know how to use it.

Also the libraries you are using to connect to the sensor cannot use interrupts.  I'm not saying they do but if the video is all messed up and the examples work for you then that is why.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

LM1881 goes from 5 V to 0 V when vertical sync is detected:



So I can attach interrupt number 0 (pin 2 on Arduino) to vertical sync output, with falling mode, so it calls a function that resets line count when the LM1881 goes 0 at vertical sync. But resetting line count won't start vertical sync at the same time; this will happen next time timer 1 calls its ISR. So both video in and OSD will be on line 0, but not perfectly synchronized.

Am I wrong? I'm not an expert, sorry if I'm missing something.

Thanks a lot!
Logged

Michigan, US
Offline Offline
Full Member
***
Karma: 3
Posts: 148
Go Huskies
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually after looking at the data sheet for the ATMega328p i think this might work:

Hook the hsync signal to the timer 1 capture pin(ICP1, PINB0, arduino pin smiley-cool, this will grab the time of the hsync and stick it into a register then reset the counter to 0.  Then in the interrupt it triggers read the register(ICR1) decide if its a normal line (vsync lines/equalizing pulse lines are "half lines") reset the counter if its not a normal line, and increment if it is.  Then on the lines we want to output on watch the timer and wait until the correct time to start outputting.

This way kind of ignores the arduino environment as i don't think there are any core libraries that will allow timer1 to be used in this manner.

This is the "easiest" solution I can think of as it uses the built in hardware to handle the majority of the work.  That being said you would have to learn all about setting up the timer, handling interrupts ect.

Also if all you want is to output i saw a OSD shield somewhere on the forums.

Edit:
some useful links on composite video if your interested:
http://www.sxlist.com/techref/io/video/ntsc.htm
batsocks has a good write up too:
http://www.batsocks.co.uk/readme/video_timing.htm
« Last Edit: May 12, 2010, 05:21:26 pm by mdmetzle » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And how about making TCNT1 = _PAL_CYCLES_SCANLINE and g_scanLine = _PAL_LINE_START_VSYNC when LM1881 detects vertical sync? This way it will start ISR as a new frame.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a way of doing video overlay / sync detection without using an LM1881, instead using the analog comparator built into the atmega. The coding is more complicated but not too bad, the analog comparator generates an interrupt and hsync and vsync can be distinguished by testing how long the comparator stays low. Look at this link for an example:

http://www.viennawireless.org/balloon/hardware/overlay/index.php

Logged


Michigan, US
Offline Offline
Full Member
***
Karma: 3
Posts: 148
Go Huskies
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was looking at that earlier today actually.  Interesting stuff, I don't know if ill implement osd at all.  I do find the idea of it interesting and that's what got me started on this library to begin with.

I have a few other things I want to add. Right now I'm working on making the resolution selectable during run time.  I also want to speed up the ISR so I can poll the serial connection, generate simple sounds ect.

Being able to use straight asm files would be very helpful with this....
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Cool 4rdu1n0
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice work mdmetzle.  smiley-wink

After testing, I was trying to place a small binary image on the TV Screen.
For this test I made two small sketches. In this test I used an small image of 10 x 10 px, as we see in figure 1.



Figure 1 - Test image 10 x 10 px

The image was created on Gimp, and saving it as grayscale image, format pgm (in ASCII mode).

Using Processing, the test image is loaded to create our vector to use in the Arduino sketch.

Code:

String [] img; // Image is m x n px
PrintWriter salida;

void setup(){

  int i;
  int Mini = 4 ;  // Begin from posc 4 of pnm or pgm file
  int Maxi = 100; // Image is 10 x 10 px

  salida = createWriter("imagen.txt");
  img = loadStrings("mA2.pgm");  //Format pnm or pgm

for (i = Mini; i <= Maxi; i++) {
  
  if ( int(img[i]) == 255) {
        
     if (i == Maxi){
     salida.print( "1");
     }else {
     salida.print( "1" + ",");
     }    
 
  }else{
    
     if (i == Maxi){
     salida.print( "0");
     }else {
     salida.print( "0" + ",");
     }    
    
  }
  
}

salida.flush();
salida.close();
exit();
  
}


void draw(){
  
}


Code 1 - Image reading, writing vector in Processing


Finally its created an small code to read the vector and load the image to the TV Screen. In figure 2 its shown the resulting output. In code 2 is one mode to read the vector.



Figure 2 - Result image on TV Screen.


Code:

#include <TVout.h>

TVout TV;
unsigned char x,y;

int img [] = {1,0,0,1,1,1,1,1,1,0,1,0,1,1,0,0,1,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1,0,0,0,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1};


  int i,p;
  int Maxi = 10; //Image size is 10 x 10, each 10 pixels is a new row
  int Maxt = 100; // Total size of the image

  int LEDR = 7;
  int LEDV = 6;

  
void setup() {

  Maxt = Maxt - 3;
  
  x = 0;
  y = 0;
  
  TV.start_render(_NTSC);

  pinMode (LEDR, OUTPUT);
  pinMode (LEDV, OUTPUT);

}

void loop() {

  digitalWrite (LEDR,0); //for debugging
  delay(500);
  digitalWrite (LEDR,1);  //for debugging
  delay(500);
  digitalWrite (LEDR,0);  //for debugging
  delay(500);

  
  p = Maxi;  
  x = 0;
  y = 0;
    
  TV.clear_screen();
  TV.print_str(0,0,"Testing ...");
  TV.delay_frame(60);

  TV.clear_screen();
  
//Reading an image
  
  for (i = 1; i < Maxt; i++){
      
      if (i < p){

       if (img[i] == 1){
      
        TV.set_pixel(x,y,0);
        // digitalWrite (LEDV,0); //for debugging
        // delay(10);
      
        }else{
      
          TV.set_pixel(x,y,1);
          //digitalWrite (LEDV,1); //for debugging
          //delay(10);

        }
      
        x++;
                              
     }else {
      
       y++;
       x = 0;
       p = p + Maxi;
  
     }
      
   }

  TV.delay_frame(60);

}


Code 2 - Arduino code to read an image.



Figure 3 - Arduino Board for testing.

Now testing how to load a bit bigger images. smiley-cool

Logged

Michigan, US
Offline Offline
Full Member
***
Karma: 3
Posts: 148
Go Huskies
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nice work spacebird.  I started to implement a method to put bitmaps onto the screen but my initial method did not work, and i decided to use my time working on fixing bugs instead.  I do know what i was doing wrong now though.  I was attempting to copy predefined bitmaps out of the flash space and wasn't reading the data back correctly.

Here is an idea assuming you are generating bitmaps that are ordered correctly you can directly copy whole bytes onto the screen; note that the most significant bit is the left most pixel.

I am interested in the processing program you use to generate the bitmaps though, it would be very useful. (Edit: oh hey you included that...)

I was using this for the bitmap I created:
http://www.crystalfontz.com/forum/showthread.php?t=5854
« Last Edit: May 13, 2010, 01:55:04 pm by mdmetzle » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Cool 4rdu1n0
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Let me see that link...

ok... I see that is a 1 bit image or binary image. For grayscale is needed a 8 bit per pixel, this could be binarize or a pre-process call binarization.

--testing if is possible to use 8 bit images with your library .

The position of the images depends of : if you are using vector form or matrix form.  At the moment due to capacity issues on Arduino Duemilanove it's hard to upload a bigger image. So now I'm planning to buy an external memory like:  http://www.arduino.cc/en/Tutorial/SPIEEPROM  

---
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 29
Cool 4rdu1n0
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I forgot to upload this code to visualize the image in processing.


Code:

int [] img = {1,0,0,1,1,1,1,1,1,0,1,0,1,1,0,0,1,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1,0,0,0,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1};

void setup(){
  
  int j,k,i;
  int Maxi = 10; //Image size is m x n, eac m pixels is a new row, use m
  int Maxt = 100; // Total size of te image -3
 
  Maxt = Maxt - 3;
  int p = Maxi;  
  j = 0;
  k = 0;
    
  for (i = 1; i < Maxt; i++){
      
      if (i < p){

        j++;
              
        if (img[i] == 1){
          print (" ");  
        }else{
          print ("*");
        }
                
     }else {
      
       k++;
       j = 0;
       println();
       p = p + Maxi;
  
     }
      
   }
 
 exit();
 
}

void draw(){
  
}

Logged

Pages: 1 2 [3] 4 5 ... 19   Go Up
Jump to: