-1

I am sending one integer variable from rpi to arduino. However, it is showing an error. Everything else is correct and here is the code which sends the data:-

from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub, SubscribeListener
import time
import numpy as np
import cv2
import serial
import RPi.GPIO as GPIO
import logging

#PubNub.set_stream_logger('recieve', logging.DEBUG)

#PubNub.SDK_VERSION

ser=serial.Serial("/dev/ttyACM0",9600)  #change ACM number as found from ls /dev/tty/ACM*
ser.baudrate=9600
ser.flushInput()

GPIO.setmode(GPIO.BOARD)
#GPIO.setup(11, GPIO.OUT)

pnconfig = PNConfiguration()
pnconfig.subscribe_key = "sub-c-fefb53da-045f-11ea-a185-1a72d7432d4b"
pnconfig.publish_key = "pub-c-811efe68-1f19-4cbc-9583-473ef14f04f5"
pnconfig.ssl = False

print("Code Run")

pubnub = PubNub(pnconfig)

print("lol1")

my_listener = SubscribeListener()
print("lol2")
pubnub.add_listener(my_listener)
print("lol3")
pubnub.subscribe().channels('recieve').execute()
print("lol4")
my_listener.wait_for_connect()

print("connected")

#pubnub.publish().channel("my_channel").message('hello there').sync()
result = my_listener.wait_for_message_on('recieve')
print(result.message)

if (result.message == 'point+B'):
        print("msg send")
        time.sleep(1)
        video_capture = cv2.VideoCapture(0)
        print("video activated")

        while(True):
                # Capture the frames

                ret, frame = video_capture.read()
                print("image processing on")

                crop_img = frame[0:1200, 0:700]
                gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)

                # Gaussian blur
                blur = cv2.GaussianBlur(gray,(5,5),0)

                # Color thresholding
                ret,thresh = cv2.threshold(blur,60,255,cv2.THRESH_BINARY_INV)

                # Find the contours of the frame
                #contours,hierarchy = cv2.findContours(thresh.copy(), 1, cv2.CHAIN_APPROX_NONE)                    
                _, contours, _= cv2.findContours(thresh.copy(), 1, cv2.CHAIN_APPROX_NONE)

                # Find the biggest contour (if detected)
                if (len(contours) > 0):
                        c = max(contours, key=cv2.contourArea)
                        M = cv2.moments(c)
                        cx = int(M['m10']/M['m00'])
                        cy = int(M['m01']/M['m00'])
                        cv2.line(crop_img,(cx,0),(cx,720),(255,0,0),1)
                        cv2.line(crop_img,(0,cy),(1280,cy),(255,0,0),1)
                        cv2.drawContours(crop_img, contours, -1, (0,255,0), 1)
                        print(cx)
                        #cv2.imshow('frame',crop_img)
                        str(cx)
                        #cx = cx + str('\n')
                        write_ser=ser.write(cx.encode())
                        #write_ser=ser.write(cx)

                        int(cx)
                        if cx >= 450:
                                print ("Turn Right!")

                        if cx < 400 and cx > 300:
                                print ("On Track!")

                        if cx <= 50:
                                print ("Turn Left!")
                        else:
                                print ("I don't see the line")

                    #Display the resulting frame
                    cv2.imshow('frame',crop_img)
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                            break

                    #cap.release()
                    #cv2.destroyAllWindows()

console:-

Code Run
lol1
lol2
lol3
lol4
connected
point+B
msg send
video activated
image processing on
222
Traceback (most recent call last):
  File "/home/pi/Desktop/Transporter codes/Final_transporter.py", line 97, in <module>
    write_ser=ser.write(cx.encode())
AttributeError: 'int' object has no attribute 'encode'

I tried converting to string variable but didn't work. What is the solution?

Roger Jones
  • 1,494
  • 7
  • 14
suu
  • 37
  • 4
  • 1
    So, cx is a Python integer? What did you expect the encoded form to be? How did you try a string, and what happened that it didn't work? (Please edit this information into your question rather than replying as a comment.) – Bob Brown Feb 12 '20 at 14:04
  • 1
    Nothing to do with the Raspberry Pi. – joan Feb 12 '20 at 16:09
  • why did you use an arduino tag or even the serial tag? ... your question is about python – jsotola Feb 12 '20 at 20:15
  • @susu, Welcome and nice to meet you. Ah, let me see. When I first read the statement "write_ser = ser.write(cx.encode()), I became nervous, because I could tell which language it uses, is it Arduino Mega C++, or Google Go, or Scala, or Node.Red. I was too afraid to ask, worrying other elites would LOL at my stupid question. I now think that this specific question might belong to the big or general question of "How can Rp talk to Arduino", then I have no worries, because I am a ninja in Rpi talking to Xduino, using python and serial UART, perhaps one of my old posts might help. – tlfong01 Feb 13 '20 at 01:26
  • Reference 10 of The Lazy's answer to the following Rpi UART/serial question explains how Rpi can talk to Arudino (actually any device talking serial) using Python UART/serial: https://raspberrypi.stackexchange.com/questions/105223/how-can-rpi4b-use-uart-to-read-and-analyze-received-data-at-a-3dr-fpv-air-radio. – tlfong01 Feb 13 '20 at 01:56
  • I added more information and code so have a look. Problem is in communication between pi & arduino so included the tag as well. – suu Feb 13 '20 at 07:39

1 Answers1

1

The error message you are getting says 'int' object has no attribute 'encode', the encode method is only available for objects of type str.

I believe you want the str() function instead to convert the integer into a string (or byte array) that the write function can then use. You also mention (in the comments) that the Arduino side is only receiving the data when you add a newline character to the newly created string: this is probably because the Arduino code is using something like readline and is looking for an EOL character.

As an aside, some might argue that converting cx into a string and putting it into the same variable and then adding the newline for sending is poor form, especially if you then convert it back into an integer later on. A more "readable" line of code that's easier to see what's going on and a bit more compact might be something like...

# Send CX as an ASCII string over the serial connection, terminate with newline.
write_ser = ser.write( str( cx ).encode( 'ascii' ) + b'\n' )
Roger Jones
  • 1,494
  • 7
  • 14
  • 1
    right answer but 2 more lines after str(cx):- cx = cx + '/n', ser.write(cx.encoding('ascii')) .Then it sends data to arduino. Thats what I found just recently. – suu Feb 14 '20 at 10:06
  • 1
    @suu I've added some more information to my answer that might help with adding the '\n' to the string. – Roger Jones Feb 14 '20 at 10:54
  • cool, sounds good – suu Feb 15 '20 at 12:38